Як надрукувати вміст файлу лише у тому випадку, якщо перший рядок відповідає певній схемі?


11

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

Як перевірити зразок? Чи є спосіб перевірити шаблон і на основі результату зробити щось ..

РЕДАКТУВАННЯ. Погляньте на це питання: /programming/5536018/how-to-get-match-regex-pattern-using-awk-from-file

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


1
Який результат ви очікуєте? Який шаблон ви шукаєте? Що ви пробували поки що?
tachomi

@tachomi відредаговано, будь ласка, подивіться
Матвій

Відповіді:


17

Ви можете зробити це за допомогою ed:

ed -s infile <<\IN 2>/dev/null
1s/PATTERN/&/
,p
q
IN

хитрість тут полягає в тому, щоб спробувати замінити PATTERNна 1stсобі. edпомилиться, якщо він не зможе знайти заданий шаблон, тому ,p(друкувати весь файл) буде виконуватися лише у випадку 1s/PATTERN/&/успіху.

Або з sed:

sed -n '1{
/PATTERN/!q
}
p' infile

це застосовується, qякщо перший рядок не ( !) збігається PATTERN, інакше він pпозначає всі рядки.
Або, як вказував Тобі Спейт , з GNU sed:

sed '1{/PATTERN/!Q}' infile

Qтакий же, як, qале він не друкує простір шаблону.


Ви можете Qзамість qGNU sed або dраніше q(портативний), щоб не вимагати -nпрапор і pкоманду: sed '1{/PATTERN/!Q}' infileабо sed -e '1{' -e '/PATTERN/!{' -e 'd' -e 'q' -e '}' -e '}' infile, відповідно.
Toby Speight

dперезапускає командний цикл, який мене завжди виловлює! : - |
Toby Speight

У GNU sedперша sedкоманда скаржиться sed: -e expression #1, char 10: extra characters after command(через p), але edостання sedпропозиція працює добре.
Skippy le Grand Gourou

Примітка: Рішення, надані цією відповіддю, мають перевагу, ніж інші відповіді, що вони можуть бути застосовані на трубі.
Skippy le Grand Gourou

1
@SkippyleGrandGourou - ви спробували перетворити його на однолінійку, не розділяючи команди з крапками з комою - це правильний спосіб зробити цеsed -n '1{/PATTERN/!q};p'
don_crissti

15

З скринькою інструментів POSIX:

{ head -n 1 | grep pattern && cat; } <file

1
{double} <солодкий.
mikeserv

@mikeserv: Я маю намір використовувати його, щоб запобігти плутанині нової людини, але відредагований Стефан зрозуміліший.
cuonglm

8
 awk '/pattern/{print FILENAME}; {nextfile}' ./*.txt

надрукував би ім'я не прихованих txtфайлів у поточному каталозі, перший рядок якого збігається з розширеним регулярним виразом patternіз тими awkдодатками, які підтримуютьnextfile .

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

 awk 'FNR == 1 && ! /pattern/ {nextfile}; {print}' ./*.txt

Це ефективно тому, що він виконує лише одну команду, але awk, не є найбільш ефективною командою для скидання вмісту файлу, з великими файлами, ви можете отримати кращі показники, виконавши щось на кшталт:

 awk '/pattern/{printf "%s\0", FILENAME}; {nextfile}' ./*.txt |
   xargs -r0 cat

Тобто використовуйте лише awkдля друку списку файлів, які відповідають (0-розділеним), і покладаєтесь на catскидання їх вмісту.


6

Якщо ви пишете сценарій оболонки, ви можете щось подібне

for file in ./*; do head -n 1 "$file" | grep -q 'PATTERN' && cat "$file"; done

Або в Perl:

perl -Tlne '$f = /PATTERN/ if $. == 1; print if $f; $. = 0 if eof' ./*

@ Stéphane Chazelas: Можливо, close ARGVце більше ідіома, ніж привласнення $..
cuonglm

@terdon Yourrs виглядає як кодовий гольф, все в одному рядку, без дужок навколо назв змінних і не заохочує чисту структуру. А у вас був знак пропущеного долара, коли я публікував, це просто не спосіб навчання баш. Я припускаю, що ці фактори походять із передумови, який у вас теж є, тому вам пробачать! ;)

@guest привіт і ласкаво просимо на сайт! Я перетворив вашу відповідь на коментар, оскільки відповіді слід розміщувати, лише якщо вони відповідають на власне питання. Це не форум у класичному розумінні, і ми хочемо лише тут чистого питання та відповідей. Ви можете завітати у довідковий центр або здійснити екскурсію, щоб краще зрозуміти сайт. Однак, мій досвід є в біології, так, так, мій код далеко не чистий :) Однак я не бачу, як дужки допоможуть тут, цитати вже захищають змінну. Що зламає це, від чого захищатимуть дужки?
terdon

@guest ах, вибачте, забув, що ви не можете коментувати. Сміливо заходьте і пояснюйте в чаті , я впевнений, що я можу щось навчитися.
terdon

5

Oldschool, просто перекладіть своє речення в стандартні команди:

for file in *; do
    if head -n 1 "${file}" | grep -q 'PATTERN'; then
        cat "${file}"
    fi
done

Навчання башу - це гарний початок. Якщо вам просто потрібно швидке рішення, спробуйте відповіді sed-, awk- або perl. І приємно, але це власні мови, які потрібно (і, напевно, хочеш) вивчити.

Це досить простий приклад, тому, якщо ви хочете дізнатися більше, ви можете також спробувати те ж саме в ruby, php, js (наприклад, у nodejs) або будь-якій іншій мові, яка дозволяє отримати доступ до файлів. Навіть C / C ++ або Java повинні легко управляти з невеликим завданням.


1
Це в основному те саме, що і моє, за винятком того, що ви використовуєте if/elseзамість цього [ ] &&.
terdon
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.