行頭の^アンカーが機能していても、行末の$アンカーがgrepコマンドで機能しないのはなぜですか?


19

UNIXには非常に新しいですが、プログラミングには新しいものではありません。MacBookでターミナルを使用します。クロスワード構築のために単語リストを管理および検索するために、Grepコマンドとそのバリエーションを手に入れようとしています。かなり簡単そうに思えますが、単純なケースだと思っていたものに早く夢中になります。

私が入るとき

grep "^COW" masternospaces.txt

欲しいものが得られます。COWで始まるすべての単語のリストです。

しかし、私が入るとき

grep "COW$" masternospaces.txt

COWで終わる単語のリストを取得する予定です(そのような単語は多数あります)が、何も返されません。

このファイルはプレーンテキストファイルで、すべての行がすべて大文字で単語(またはスペースを含まない単語フレーズ)になっています。

ここで何が起こっているのでしょうか?


3
masternospaces.txtファイルの起源は何ですか?UnixスタイルのLFの代わりにWindowsスタイルの行終端(CR-LF)を使用することは可能ですか?
スチールドライバー14

2
確かではありませんが、リストの単語または行のリストを探していますか?
mikeserv 14

スチールドライバー-そのような何かが私の最初の考えでした。そこに何が起こっているのか、可能性すら何なのかを調べる方法がわからなかった。終了リターンが終了リターンであると仮定しました。そのファイルは、いくつかのソースからの大要です。どのファイルが元のファイルと見なされるかさえわかりません。また、PCとMacの両方のマシンで少なくとも3つのワードプロセッサを使用しています。使用している終端の種類を確認する最良の方法は何でしょうか?
DTalvacchio 14

mikeserv--この.txtファイルでは、すべての行は単なる単語(または単語間にスペースのないフレーズ、つまり「単語」)です。だから私は行を探している、と思う。。。ただ、各行には、クロスワード用の単語として考えているものの1つだけが含まれています。
DTalvacchio 14

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-> LF0d-> CR
user43791 14

回答:


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-> LF0d-> 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

行末を変更するには

さまざまなツールを使用して行末を変更するさまざまな方法については、こちらまたはこちらをご覧ください。

vim masternospaces.txt
:set fileformat=unix
:wq

何も変更せずにgrepする

grep行末に関係なく一致させたい場合は、常に次のように行末を指定できます。

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

空白行が表示されている-v場合は、次のオプションを使用して、実際に何かに一致したことを確認できますcat

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

私の個人的なお気に入り

また、次を使用してgrepと出力の標準化の両方を行うこともできますsed

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

どこ^Mに入力することによって得られるCtrl-V Ctrl-Mキーボード上。

お役に立てれば!


それはすべて非常に役立ちます。今日は時間がありませんが、明日はこのすべてを詳しく調べて、何が何であるかを確認します。それまでの間、お気に入りのUnixコマンドリファレンスガイドへのリンクがあり、物事がどのように機能しているのかを少し教えていただければ幸いです。私はあちこちで作品を拾ってきましたが、説明のための私の頼りになる情報源をまだ見つけていません。ありがとう --D
DTalvacchio 14

少なくとも私にとっては、この投稿が閉鎖されていないのは残念です。私の人生では、行末を一致させる方法を理解することはできません。16進ダンプを行うと、上記の例のような行末が見当たりません。私はヘックスでの作業に慣れていないので、正しく読んでいないかもしれません。また、[[:cntrl:]]提案された@ user43791を試してみましたが、まだ何も一致していません。これは意味がありません。私は、GNU grepの2.20を使用して、テキストファイルに書き込まれたnDPIからの出力の解析よ
harperville

@harpervilleあなたならcat -v yourfile.ext、何が見えますか?
user43791

まあ、エキサイティングまたは予期しないことに何も。ちょうど私がそれらを見ると予想される内容。あなたが探している特定のものは何ですか?ここに出力を貼り付けることはできませんが、内容だけが表示されます。によると、通常の「ASCII ASCIIテキスト」file
ハーパービル

@harperville各行の最後に余分な「^ M」はありませんか?ヘックスの最初の数行を貼り付けていただけますか?
user43791

1

@ user43791の回答のように)grepで「標準」のRegEx構文を使用できますが、grepには入力境界を示す他の識別子もあります。

行全体の開始と終了のマッチャーは、\`(バックティック)(代わりに^)および\'(アポストロフィ)(代わりに$)です。

したがって、元のコマンドには次を使用します。 grep "COW\'" masternospaces.txt

サイドノート:それはあることに注意することも重要だ?+あなたがそれらを使用してエスケープしない限り、文字通り扱われ、\?そして\+それらに彼らの正規表現スタイルのセレクタの対応を行うこと。

ソース:grep正規表現の構文


grepは開始に^(キャレット)を、終了に\ '(アポストロフィ)を使用しています
-GypsyCosmonaut

1

\rgrep の前を削除する別の方法:

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

[[:cntrl:]]は長い間そのようなことを覚えていないので、それは非常に明確であることが好きです。


-2

"COW $"は、bashがgrepのパラメーターを設定したときに、$がエスケープシンボルであるため、 "$"を ""として扱う 'COW'として解釈されました。$が仲間になっていなかった場合、bashシェルでは空の文字列として解釈されるため、代わりにgrep 'COW $' masternospaces.txtを使用する必要があります。


3
の有効な展開がないため$、bashによってそのまま残され、grepによって使用されます。自分で見てください:echo "COW$"- $まだそこにあります。
ジェフシャラー

-3

BSD grepでは、「$」をエスケープし、文字列を二重引用符で囲む必要があります。

"COW\$"

1
いいえ。これ$はシェルにとって特別なものではありません。なぜなら、その後のものは有効なシェル変数名ではないからです。静的な文字列を単一引用符で囲むことは良い考えですが、ここでは違いはありません。
クサラナナンダ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.