Как найти последнее поле, используя 'cut'

Без использования sed или awk, только cut, как мне получить последнее поле, когда количество полей неизвестно или изменяется с каждой строкой?

Ответ 1

Вы можете попробовать что-то вроде этого:

echo 'maps.google.com' | rev | cut -d'.' -f 1 | rev

Объяснение

  • maps.google.com reverse будет moc.elgoog.spam
  • cut использует точку в качестве разделителя и выбирает первое поле, которое moc
  • Наконец, мы снова отменим его (спасибо за напоминание, @tom), чтобы получить com

Ответ 2

Используйте расширение параметра. Это намного эффективнее любой внешней команды, включая cut (или grep).

data=foo,bar,baz,qux
last=${data##*,}

См. BashFAQ # 100 для ознакомления с встроенной обработкой строк в bash.

Ответ 3

Невозможно использовать только cut. Ниже приведен пример использования grep:

grep -o '[^,]*$'

Замените запятую для других разделителей.

Ответ 4

Без awk?... Но это так просто с awk:

echo 'maps.google.com' | awk -F. '{print $NF}'

AWK - намного более мощный инструмент, чтобы иметь в своем кармане. -F if для разделителя полей NF - количество полей (также обозначает индекс последнего)

Ответ 5

Существует несколько способов. Вы также можете использовать это.

echo "Your string here"| tr ' ' '\n' | tail -n1
> here

Очевидно, что пустой пробел для команды tr должен быть заменен разделителем, который вам нужен.

Ответ 6

Это единственное решение, которое можно использовать только для вырезания:

echo "s.t.r.i.n.g." | cut -d '.' -F2- [repeat_follow_part_forever_or_until_out_of_memory:] | cut -d '.' -f2 -

Используя это решение, количество полей действительно может быть неизвестным и время от времени меняться. Однако, поскольку длина строки не должна превышать символы LINE_MAX или поля, включая символ новой строки, то произвольное количество полей никогда не может быть частью реального условия этого решения.

Да, очень глупое решение, но единственное, что соответствует критериям, которые я думаю.

Ответ 7

следующее реализует предложение друга

#!/bin/bash
rcut(){

  nu="$( echo $1 | cut -d"$DELIM" -f 2-  )"
  if [ "$nu" != "$1" ]
  then
    rcut "$nu"
  else
    echo "$nu"
  fi
}

$ export DELIM=.
$ rcut a.b.c.d
d

Ответ 8

Если у вас есть файл с именем filelist.txt, который является списком путей, таких как: с:/dir1/dir2/file1.h C:/dir1/dir2/dir3/file2.h

то вы можете сделать это: rev filelist.txt | cut -d "/" -f1 | ред

Ответ 9

Если ваша входная строка не содержит прямой косой черты, вы можете использовать basename и подоболочку:

$ basename "$(echo 'maps.google.com' | tr '.' '/')"

Он не использует sed или awk но также не использует cut, так что я не совсем уверен, может ли это быть ответом на вопрос как его формулировка.

Это не очень хорошо работает, если обрабатывать входные строки, которые могут содержать косую черту. Обходной путь для такой ситуации - заменить косую черту другим символом, который, как вы знаете, не является частью допустимой входной строки. Например, символ pipe (|) также не разрешен в именах файлов, поэтому это будет работать:

$ basename "$(echo 'maps.google.com/some/url/things' | tr '/' '|' | tr '.' '/')" | tr '|' '/'

Ответ 10

Добавление подхода к этому старому вопросу просто для удовольствия:

$ cat input.file # file containing input that needs to be processed
a;b;c;d;e
1;2;3;4;5
no delimiter here
124;adsf;15454
foo;bar;is;null;info

$ cat tmp.sh # showing off the script to do the job
#!/bin/bash
delim=';'
while read -r line; do  
    while [[ "$line" =~ "$delim" ]]; do
        line=$(cut -d"$delim" -f 2- <<<"$line")
    done
    echo "$line"
done < input.file

$ ./tmp.sh # output of above script/processed input file
e
5
no delimiter here
15454
info

Только резать и колотить. Ну и эхо, наверное.

Ответ 11

Добавление подхода к этому старому вопросу просто для удовольствия:

$ cat input.file # file containing input that needs to be processed
a;b;c;d;e
1;2;3;4;5
no delimiter here
124;adsf;15454
foo;bar;is;null;info

$ cat tmp.sh # showing off the script to do the job
#!/bin/bash
delim=';'
while read -r line; do  
    while [[ "$line" =~ "$delim" ]]; do
        line=$(cut -d"$delim" -f 2- <<<"$line")
    done
    echo "$line"
done < input.file

$ ./tmp.sh # output of above script/processed input file
e
5
no delimiter here
15454
info

Помимо bash, используется только разрез. Ну и эхо, наверное.

Ответ 12

Я понял, что если мы просто убедимся, что конечный разделитель существует, он работает. Так что в моем случае у меня есть запятые и пробелы. Я добавляю пробел в конце;

$ ans="a, b"
$ ans+=" "; echo ${ans} | tr ',' ' ' | tr -s ' ' | cut -d' ' -f2
b