Как мне получить последнее слово в каждой строке с помощью bash

80

Например, у меня есть файл:

$ cat file

i am the first example.

i am the second line.

i do a question about a file.

и мне нужно:

example, line, file

Я намерен использовать "awk", но проблема в том, что слова находятся в другом месте

Камило Сото
источник
1
Ваша «вторая строка» не находится на второй строке из-за пустых строк, пожалуйста, приводите менее двусмысленные примеры в будущем.
Адриан Фрювирт

Ответы:

93

Пытаться

$ awk 'NF>1{print $NF}' file
example.
line.
file.

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

{
    sub(/\./, ",", $NF)
    str = str$NF
}
END { print str }

вывод:

$ awk -f script.awk file
example, line, file, 

Чистый баш:

$ while read line; do [ -z "$line" ] && continue ;echo ${line##* }; done < file
example.
line.
file.
Фредрик Пиль
источник
@Fredrik Pihl, не могли бы вы добавить пояснения к каждому разделу кода, например: «этот код печатает последнее поле, полученное awk при печати $NF»?
Алексей Магура
не могли бы вы объяснить echo $ {line ## *};
code4cause
1
@ code4cause - просто Гото gnu.org/software/bash/manual/bash.html и искать ##или просто попробовать его в раковине.
Fredrik Pihl
Не возвращает ничего, если есть только одно слово. $ echo "foo" | awk 'NF> 1 {print $ NF}' $
Итан Пост
85

Вы можете легко сделать это с помощью grep:

grep -oE '[^ ]+$' file

( -Eиспользовать расширенное регулярное выражение; -oвыводить только совпавший текст вместо полной строки)

ричи
источник
3
Должно быть grep -oE '[^ ]+$', вы хотите видеть вкладку здесь из-за поведения браузера, но в любом случае здесь учитываются и пространства вкладок, или, что еще лучше, вы можете это сделать,grep -oE '[^[:space:]]+$'
Набиль Кадими
32

В awk можно сделать что-то вроде этого:

awk '{ print $NF }'

Изменить: чтобы избежать пустой строки:

awk 'NF{ print $NF }'
Хэл Кэнэри
источник
1
Это также напечатает пустые строки
Fredrik Pihl
12

Другой способ сделать это в обычном bash - использовать следующую revкоманду:

cat file | rev | cut -d" " -f1 | rev | tr -d "." | tr "\n" ","

По сути, вы меняете строки файла, затем разделяете их, cutиспользуя пробел в качестве разделителя, берете первое поле, которое cutсоздает, а затем снова меняете токен, используете tr -dдля удаления ненужных символов и trснова для замены символов новой строки на,

Кроме того, вы можете избежать появления первого кота, выполнив:

rev < file | cut -d" " -f1 | rev | tr -d "." | tr "\n" ","
Хигуаро
источник
Это гораздо более простое решение! Ценю мысли!
Captain Woof,
6

Есть много способов. как awkпоказывают решения, это чистое решение

Решение sed - удалить что-либо до последнего пробела. Так что, если в конце нет места, он должен работать

sed 's/.* //g' <file>

вы также можете избежать sedи пойти на whileпетлю.

while read line
do [ -z "$line" ] && continue ;
echo $line|rev|cut -f1 -d' '|rev
done < file

он читает строку, уважает ее, отсекает первую (т.е. последнюю в оригинале) и восстанавливает обратно

то же самое можно сделать в чистом виде

while read line
do [ -z "$line" ] && continue ;
echo ${line##* }
done < file

это называется расширением параметров

абасу
источник
6

tldr;

$ awk '{print $NF}' file.txt | paste -sd, | sed 's/,/, /g'

Для такого файла

$ cat file.txt
The quick brown fox
jumps over
the lazy dog.

данная команда напечатает

fox, over, dog.

Как это устроено:

  • awk '{print $NF}' : печатает последнее поле каждой строки
  • paste -sd,: читает stdinпоследовательно (по -sодному файлу за раз) и записывает поля с разделителями-запятыми ( -d,)
  • sed 's/,/, /g': substitutes ","с ", " gлобалли (для всех экземпляров)

Рекомендации:

рубики
источник
Хотя этот код может ответить на вопрос, предоставление дополнительного контекста относительно того, почему и / или как этот код отвечает на вопрос, значительно улучшило бы его долгосрочную ценность. Пожалуйста, отредактируйте свой ответ, чтобы добавить пояснение.
Тоби Спейт