Чому кінцевий рядок $ anchor не працює з командою grep, незважаючи на те, що ^ якор переднього рядка?


19

Дуже нова для UNIX, але не нова для програмування. Використання терміналу на MacBook. Для управління та пошуку списків слів для побудови кросвордів я намагаюся скористатися командою Grep та її варіантами. Здається, це досить просто, але зависнути рано на тому, що я вважав, що це просто.

Коли я входжу

grep "^COW" masternospaces.txt

Я отримую те, що хочу: список усіх слів, що починаються з COW.

Але коли я входжу

grep "COW$" masternospaces.txt

Я очікую отримати список слів, що закінчуються на COW (таких слів багато), і взагалі нічого не повертається.

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

Будь-яка ідея, що може статися тут?


3
Яке походження файлу masternospaces.txt? чи можливо, він має лінійні закінчення у стилі Windows (CR-LF) замість УНФ-стилю в Unix?
steeldriver

2
Не впевнені, але ви шукаєте слова зі списком чи список рядків ... ?
mikeserv

steeldriver-- Щось таке було моєю першою думкою. Не знав, як перевірити, що там відбувається, або які навіть можливості були. Припускали, що кінцеве повернення - це кінцеве повернення. Цей файл є масовим збірником з кількох джерел. Я навіть не впевнений, який із них вважався б оригінальним файлом. І пройшло щонайменше три текстових процесора на ПК та Mac машинах. Що може бути найкращим способом побачити, які термінали він використовує?
DTalvacchio

mikeserv - У цьому .txt-файлі кожен рядок - це лише слово (або фраза без пробілів між словами, тому знову "слово"). Тож я шукаю лінії, гадаю. . . тільки що в кожному рядку є лише одне з того, що я розглядаю слово для кросвордів.
DTalvacchio

1
Ви можете hexdumpперевірити, як саме форматовано закінчення рядка. Я пропоную вам використовувати мій улюблений формат: hexdump -e '"%08_ad (0x%08_ax) "8/1 "%02x "" "8/1 "%02x "' -e '" "8/1 "%_p""|"8/1 "%_p""\n"' masternospaces.txt. З виходом перевірте закінчення рядків: 0a-> LF, 0d-> CR.
user43791

Відповіді:


23

Як зазначав @steeldriver, проблема, ймовірно, буде викликана іншим стилем закінчення рядка, ніж те, що grepочікується.

Щоб перевірити закінчення рядків

Ви можете hexdumpперевірити, як саме форматовано закінчення рядка. Я пропоную вам використовувати мій улюблений формат:

hexdump -e '"%08_ad (0x%08_ax)    "8/1 "%02x ""   "8/1 "%02x "' -e '"    "8/1 "%_p""|"8/1 "%_p""\n"' masternospaces.txt

З виходом перевірте закінчення рядків: 0a-> LF, 0d-> CR. Дуже швидкий приклад може дати щось подібне:

$ hexdump -e '"%08_ad (0x%08_ax)    "8/1 "%02x ""   "8/1 "%02x "' -e '"    "8/1 "%_p""|"8/1 "%_p""\n"' masternospaces.txt
00000000 (0x00000000)    4e 6f 20 43 4f 57 20 65   6e 64 69 6e 67 0d 0a 45    No COW e|nding..E
00000016 (0x00000010)    6e 64 69 6e 67 20 69 6e   20 43 4f 57 0d 0a          nding in| COW..

Зверніть увагу на закінчення рядків у форматі dos : 0d 0a.

Щоб змінити закінчення рядків

Ви можете побачити тут чи тут різні методи зміни закінчень рядків за допомогою різних інструментів, але для разової речі ви завжди можете використовувати vi / vim:

vim masternospaces.txt
:set fileformat=unix
:wq

Грипнути, нічого не змінюючи

Якщо ви просто хочете grepвідповідати незалежно від закінчення рядка, ви завжди можете вказати закінчення рядка таким чином:

grep 'COW[[:cntrl:]]*$' masternospaces.txt

Якщо відображається порожній рядок, ви можете перевірити, чи дійсно ви щось відповідали, скориставшись -vопцією cat:

grep 'COW[[:cntrl:]]*$' masternospaces.txt | cat -v

Мій особистий фаворит

Ви також можете зміцнити та стандартизувати вихід, використовуючи sed:

sed -n '/COW^M*$/{;s/^M//g;p;};' masternospaces.txt

де ^Mце отримано, набравши Ctrl-V Ctrl-Mна клавіатурі.

Сподіваюся, це допомагає!


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

Дуже погано, що ця посада не закривається, принаймні для мене. Я не можу за все життя зрозуміти, як відповідати кінці рядка. Якщо я роблю шістнадцятковий дамп, я не можу знайти приємну лінію, що закінчується, як у вашому прикладі вище. Я не знайомий з роботою з hex, тому я, можливо, не читаю це правильно. Я також спробував запропонований [[:cntrl:]]@ user43791 і для мене все ще нічого не відповідає. Це не має сенсу. Я використовую GNU grep 2.20 і аналізую вихід з nDPI, який був записаний у текстовий файл
harperville

@harperville Якщо ти cat -v yourfile.ext, що ти бачиш?
user43791

Ну, нічого цікавого чи несподіваного. Просто вміст, як я би сподівався їх побачити. Щось конкретно ви шукаєте? Я не можу вставити тут вихід, але я просто бачу вміст. Регулярний ol "" ASCII англійський текст "відповідно до file.
Харпервіль

@harperville Немає зайвих "^ M" в кінці кожного рядка? Не могли б ви вставити перші кілька шестигранних рядків?
user43791

1

Хоча ви можете використовувати «стандартний» синтаксис RegEx з grep (як у відповіді @ user43791 ), grep також має інші ідентифікатори для позначення вхідних меж.

Матчі для початку та кінця всього рядка є \`(backtick) (замість ^) та \'(апостроф) (замість $).

Отже, для вашої оригінальної команди ви використовуєте: grep "COW\'" masternospaces.txt

Примітка сторони: Важливо також відзначити , що ?і +буде розглядатися в буквальному сенсі , якщо не уникнути їх використання \?і \+зробити їх своїми колегами селекторної RegEx стилю.

Джерело: grepсинтаксис регулярного вираження


grep приймає ^ (карету) для початку, а \ '(апостроф) для кінця
GypsyCosmonaut

1

Ще один спосіб видалити \rперед grep:

... | dos2unix | egrep 'COW$' | ...

Мені подобається, що це дуже зрозуміло, оскільки я [[:cntrl:]]довго не пам’ятаю подібних речей .


-2

"COW $", коли bash встановлював параметр для grep, його інтерпретували як "COW", де трактують "$" як "", becase $ - символ втечі. коли нічого не з’єднується з $, він інтерпретується як порожній рядок через bash shell, тож слід використовувати греп 'COW $' masternospaces.txt.


3
оскільки немає коректного розширення $, воно буде залишене самим bash і використане grep. Побачте самі: echo "COW$"- $воля все одно буде.
Jeff Schaller

-3

У BSD grep вам потрібно вийти з "$" і укласти рядок у подвійні лапки:

"COW\$"

1
Гм ... ні. $Чи не буде особливою для оболонки, тому що матеріал після цього не є допустимим ім'ям змінної оболонки. Використання одинарних лапок навколо статичних рядків є кращою ідеєю, але це не має значення.
Кусалаланда
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.