Використання декількох роздільників у див


202

У мене є файл, який містить такі рядки:

/logs/tc0001/tomcat/tomcat7.1/conf/catalina.properties:app.env.server.name = demo.example.com
/logs/tc0001/tomcat/tomcat7.2/conf/catalina.properties:app.env.server.name = quest.example.com
/logs/tc0001/tomcat/tomcat7.5/conf/catalina.properties:app.env.server.name = www.example.com

У наведеному вище висновку я хочу витягнути 3 поля (№ 2, 4 і останнє *.example.com). Я отримую такий результат:

cat file | awk -F'/' '{print $3 "\t" $5}'
tc0001   tomcat7.1
tc0001   tomcat7.2
tc0001   tomcat7.5

Як я також витягую останнє поле з доменним ім'ям, яке є після '='? Як використовувати multiple delimiterдля вилучення поля?


2
Щоб відповісти на моє запитання, яке є однаковим, але різним, awkбуло ковтання полів, коли вони були порожніми, які визначали нумерацію полів. Я змінив -F " "до -F "[ ]"і awkне ковтати порожні поля більше.
Адам

Відповіді:


324

Розмежувач може бути регулярним виразом.

awk -F'[/=]' '{print $3 "\t" $5 "\t" $8}' file

Виробляє:

tc0001   tomcat7.1    demo.example.com  
tc0001   tomcat7.2    quest.example.com  
tc0001   tomcat7.5    www.example.com

42
Звичайно, catпроцес не потрібно: awk '...' file. Крім того, було б акуратніше використовувати роздільник вихідних полів:awk -F'[/=]' -v OFS="\t" '{print $3, $5, $8}'
glenn jackman

17
Awk роздільники можуть бути регулярними виразами ... це зробило мій день!
das.cyklone

4
@ das.cyklone: ​​awk також може мати кілька роздільників, з |: ex: awk -F 'this|that|[=/]' '......' (корисно мати слова / рядки, що розділяють речі) (зауважте, що це зберігає пробіли у фільмах між двома роздільниками. Додавання також |[ \t]+може бути корисним, але може зробити речі хитро ... оскільки часто є пробіли до і після "цього", це зробить 2 додаткові порожні поля між пробілами та "цим")
Олів'є Дулак

Я спробував це на двох різних дистрибутивах і отримую таку ж поведінку: я хочу отримати порт від netstat -ntpl "netstat -ntpl | sed 's /: / /' | awk '{print $ 5}'" працює, але можна обійтися без doulbe-трубопроводів. Це працює, але я не очікував, що дані в полі 17: "netstat -ntpl | awk -F" |: "'{print $ 17}'"
louigi600

2
так ... це отримало мені те, що я хотів: awk -F "[:] +" '/ \ / postmaster * $ / {print $ 5}'
louigi600

44

Гарні новини! awkроздільник поля може бути регулярним виразом. Вам просто потрібно використовувати -F"<separator1>|<separator2>|...":

awk -F"/|=" -vOFS='\t' '{print $3, $5, $NF}' file

Повернення:

tc0001  tomcat7.1  demo.example.com
tc0001  tomcat7.2  quest.example.com
tc0001  tomcat7.5  www.example.com

Тут:

  • -F"/|="встановлює роздільник поля введення на /або =. Потім він встановлює роздільник вихідного поля на вкладку.

  • -vOFS='\t'використовується -vпрапор для встановлення змінної. OFSє змінною за замовчуванням для сепаратора вихідного поля, і вона встановлюється символом вкладки. Прапор необхідний, тому що немає такого вбудованого для OFS, як -F.

  • {print $3, $5, $NF} друкує 3-е, 5-те та останнє поля на основі роздільника вхідних полів.


Дивіться інший приклад:

$ cat file
hello#how_are_you
i#am_very#well_thank#you

Цей файл має два роздільники полів #та _. Якщо ми хочемо надрукувати друге поле незалежно від того, розділювач є одним чи іншим, давайте зробимо обидва розділювачами!

$ awk -F"#|_" '{print $2}' file
how
am

Де файли пронумеровані так:

hello#how_are_you           i#am_very#well_thank#you
^^^^^ ^^^ ^^^ ^^^           ^ ^^ ^^^^ ^^^^ ^^^^^ ^^^
  1    2   3   4            1  2   3    4    5    6

1
Дякуємо @BUFU за вашу редакцію. Я видалив посилання на OFS, щоб просто зосередитись на частині FS, але також добре це мати. Ура!
fedorqui 'ТАК перестань шкодити'

5

Якщо ваш пробіл є послідовним, ви можете використовувати це як роздільник, а також замість \tпрямої вставки , ви можете встановити роздільник виводу, і він буде включений автоматично:

< file awk -v OFS='\t' -v FS='[/ ]' '{print $3, $5, $NF}'

3

Для розділювача полів будь-якого числа 2наскрізну 5букву aабо #пробіл, де розділовий символ повинен повторюватися щонайменше 2 рази і не більше 6 разів, наприклад:

awk -F'[2-5a# ]{2,6}' ...

Я впевнений, що варіанти існують за допомогою () та параметрів


3

Perl однолінійний:

perl -F'/[\/=]/' -lane 'print "$F[2]\t$F[4]\t$F[7]"' file

Ці параметри командного рядка використовуються:

  • -nпетлю навколо кожного рядка вхідного файлу, кладіть рядок у $_змінну, не друкуйте автоматично кожен рядок

  • -l видаляє нові рядки перед обробкою та додає їх згодом

  • -aрежим автоспліт - perl автоматично розділяє вхідні лінії в @Fмасив. За замовчуванням розділяється на пробіл

  • -Fмодифікатор автоспліта, у цьому прикладі розбивається на /або=

  • -e виконати код Perl

Perl тісно пов'язаний з awk, однак @Fмасив autosplit починається з індексу, $F[0]а поля awk починаються з $ 1.


2

Ще один варіант - використовувати опцію -F, але передайте їй регулярний вираз для друку тексту між лівою та правою дужками () .

Вміст файлу:

528(smbw)
529(smbt)
530(smbn)
10115(smbs)

Команда:

awk -F"[()]" '{print $2}' filename

результат:

smbw
smbt
smbn
smbs

Використовуючи awk, щоб просто надрукувати текст між ними [] :

Використовуйте, awk -F'[][]' але awk -F'[[]]' не вийде.

http://stanlo45.blogspot.com/2020/06/awk-multiple-field-separators.html


Ваша відповідь з’явилася в черзі на видалення, оскільки 9 разів з 10 користувачів, які мають 1 репутацію, що посилається на свій власний блог, зазвичай є спамом. Але ваше - виняток із правила. Останні 10 років вмісту є золота шахта, сподіваємось, у вас є план її увічнити.
Ерік Лещинський

0

Я бачу, що на дошці багато досконалих відповідей, але все ж я хотів би також завантажити свій фрагмент коду,

awk -F"/" '{print $3 " " $5 " " $7}' sam | sed 's/ cat.* =//g'


2
print $3 " " $5 " " $7може бути надруковано так само print $3, $5, $7. Крім того, я не бачу переваги використання awk, а потім трубопроводу до sed. Взагалі, awk може вистачити, і інші відповіді показують, що.
fedorqui 'ТАК перестаньте шкодити'
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.