正規表現を使用して行のN番目のフィールド文字列を照合する方法は?

正規表現を使用して行のN番目のフィールド文字列を照合する方法は?

私は15番目の単語のすべての行で文字列 "RAV"を一致させようとしています。各単語は「|」(パイプ)で区切られます。行にこの文字列があるかどうかを比較する必要があります。それでは、次のステップに進みます。

私はこれを試しています

((((?:[^|]*\|){17}(.*?)\|)+\|[^|]*$)|[^|]+(?=(\,\H\,))|(^([0-9]){4})|(([RAV]){3}))

しかし、最初、2番目、または他のフィールドが「RAV」の場合でも、これは一致します。フィールド 15 で正確に一致する項目が必要です。

答え1

必ずしも正規表現を使用する必要はありません。

そしてawk

awk -F '|' '$15 == "RAV" { print }' myfile

myfileこれにより、15番目の|区切りフィールドが正確に文字列であるファイルのすべての行が印刷されますRAV。これは正規表現の一致ではなく文字列比較を使用します。

RAV15番目のフィールドの任意の位置で部分文字列に一致させるには、次のようにします。

awk -F '|' '$15 ~ /RAV/ { print }' myfile

これはRAV正規表現を拡張し、それを15番目の区切りフィールドのデータと一致させるために使用されます|。一致するものがあれば、現在の行を印刷します。

これが呼び出すのが難しい言語awk(シェルスクリプト以外の言語)で書かれた一部のスクリプトまたはプログラムの一部である場合は、区切り文字で文字列を分割し、|15番目の要素を選択して比較します。

awk擬似コード言語として使用すると、次のようになります。

nf = split($0, a, "|")
if (nf < 15)
    print "Not enough fields!" >"/dev/stderr"
else {
    if (a[15] == "RAV") print
}

またはPerlでは(今回はエラーを確認しません)

my @a = split /\|/, $string;
if ($a[15] eq "RAV") {
    print $string
}

上記の各バリエーション(初期awkコマンドを含む)では、print15番目のフィールドが一致すると判断した後にデータに対して実行する必要があるすべての操作を表しますRAV

答え2

grep -E '^([^|]*\|){14}[^|]*RAV' infile
  • (...)別れ予選と呼びました。
  • {N}これを固定間隔数量子と呼びます。
  • (...){N}グループ予選でN回対決してください。

答え3

正規表現を使うことはできますが、こんな。はい。それについて。awk同様にフィールド分割を実行することもできます。理由がわかりますか?

$ cat input
ok|x|x|x|x|x|x|x|x|x|x|x|x|x|RAV
ok|x|x|x|x|x|x|x|x|x|x|x|x|x|RAV|bar
bad|x|x|x|x|x|x|x|x|x|x|x|x|x|NOPE
bad|x|x|x|x|x|x|x|x|x|x|x|x|x|NOPE|bar
$ sed -E -n '/^[^|]*\|[^|]*\|[^|]*\|[^|]*\|[^|]*\|[^|]*\|[^|]*\|[^|]*\|[^|]*\|[^|]*\|[^|]*\|[^|]*\|[^|]*\|[^|]*\|RAV(\||$)/p' input
ok|x|x|x|x|x|x|x|x|x|x|x|x|x|RAV
ok|x|x|x|x|x|x|x|x|x|x|x|x|x|RAV|bar

この[^|]*\|フォームは基本的に「フィールド一致」を意味します。フィールドは決してエスケープできず、15番目のフィールドを処理する前に14回|繰り返されます(私は一度vi入力しました)。14iとても逆重くメンテナンスが難しいです。

代わりにPSを使用してくださいawk

答え4

Raku(以前のPerl_6)の使用

raku -ne '.put if / ^ [ .+ ]**14 % "|" RAV /;' 

上記の回答は素晴らしいですが、Rakuはこの種の問題を大幅に簡素化する新しい、美しく、修正された数量子を%提供します。%%文書によると:%「コンマで区切られた値などの項目をより簡単に一致させるには、上の数量子に修飾子を追加して、各一致間に現れる区切り文字を指定できます。」変更された数量子は、%%末尾のコンマなどの末尾の区切り文字を受け入れます。

原子を含む上記のコードでは、[ .+ ]各列には1つ以上の文字(スペースを含む)が必要です。これは[ \S+ ](空白ではなく1つ以上の文字)または[ .* ](0文字以上の文字)に変更することもできます。

また、他の答えと同様に、|縦棒で分割することでこの問題を解決できます。

raku -ne '.put if .split("|")[14] eq "RAV" // next;'  

#OR

raku -ne '.split("|")[14] eq "RAV" ?? $_.put !! next;'  

入力例(@thrigのおかげで):

ok|x|x|x|x|x|x|x|x|x|x|x|x|x|RAV
ok|x|x|x|x|x|x|x|x|x|x|x|x|x|RAV|bar
bad|x|x|x|x|x|x|x|x|x|x|x|x|x|NOPE
bad|x|x|x|x|x|x|x|x|x|x|x|x|x|NOPE|bar

出力例:

ok|x|x|x|x|x|x|x|x|x|x|x|x|x|RAV
ok|x|x|x|x|x|x|x|x|x|x|x|x|x|RAV|bar

https://raku.org

関連情報