Як отримати останнє слово в кожному рядку з 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"?
Олексій Магура

не могли б ви пояснити ехо $ {рядок ## *};
code4 Тому що

1
@ code4cause - просто перейдіть на gnu.org/software/bash/manual/bash.html і знайдіть ##або просто спробуйте в оболонці.
Фредрік Піл,

Нічого не повертає, якщо є лише одне слово. $ 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
Це також надрукувало б порожні рядки
Фредрік Піл,

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" ","

Це набагато простіше рішення! Я ціную роздуми!
Капітан Вуф

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локально (для всіх випадків)

Список літератури:


Хоча цей код може відповісти на питання, надання додаткового контексту щодо того, чому та / або як цей код відповідає на питання, значно покращило б його довгострокову цінність. Будь ласка, відредагуйте свою відповідь, щоб додати пояснення.
Тобі Спейт
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.