次のようなランダムな行を持つファイルがあります。
aaa bbb
ccc ddd
eee mark: 98 fff
ggg ggg jjjj iii
jjj kkkk
awkとgensubだけを使って上記の数字「98」を一致させたい。これまでに以下のコードがありますが、gensubに "\ n"を別の文字として扱わせる必要があるため、うまくいかないようです。
cat file.txt | awk 'printf(gensub(/^.*mark: ([0-9]+).*$/,"\\1","g"))}'
上記のコードの出力は「98」のみ必要です。どうすればいいですか?
編集する
sまたはm修飾子を使用しても、私が知っている限り、「s」修飾子は正規表現を処理する必要があるため機能しません。 \n を含むすべての文字で。
答え1
awk
入力が複数行の文字列として扱われると思います。しかし、実際にはそうではありません。ファイルから awk スクリプトを実行すると、そのスクリプトが適用されます。ファイルの各行にそれぞれ。したがって、1行にgensub
1回実行します。実際に欲しいことができますが、awk
実際にはその作業に最適なツールではありません。
私が知っている限り、あなたは大きなファイルを持っていて、次の数字mark:
とスペースだけを印刷したいと思います。もしそうなら、これらすべての方法があなたの周りにとどまるよりも簡単ですgensub
。
grep
Perl準拠の正規表現と共に使用されます(-P
)$ grep -oP 'mark:\s*\K\d+' file 98
-o
製造元はgrep
ライン上の一致部分のみを印刷します。これは\K
、「このポイントの前に一致するすべてのエントリを無視します」を意味するPCRE構成です。sed
$ sed -n 's/.*mark:\s*\([0-9]\+\).*/\1/p' file 98
正常な出力を抑制します
-n
。交換が成功した場合にのみp
最後に印刷されます。sed
正規表現自体は、次の数値文字列mark:
とゼロ個以上の空白文字をキャプチャし、行全体をキャプチャされたコンテンツに置き換えます。真珠
$ perl -ne 'print if s/.*mark:\s*(\d+).*/$1/' file 98
-n
Perlに入力ファイルを1行ずつ読み、与えられたスクリプトを適用するように指示します-e
。スクリプトは、置換が成功したすべての行を印刷します。
本当に本当に使いたいなら、gensub
次のようにしてください。
$ awk '/mark:/{print gensub(/.*mark:\s*([0-9]+).*/,"\\1","g")}' file
98
個人的に私はawkでこれを行います。
$ awk '/mark:/{gsub(/[^0-9]/,"");print}' file
98
awkに複数行の入力を許可させたいと思うので、次のようにすることができます(ファイルにNULL文字がないと仮定)。
$ awk '{print(gensub(/^.*mark: ([0-9]+).*$/,"\\1","g"))}' RS='\0' file
98
RS='\0'
入力レコード区切り記号(つまり定義された「行」awk
)をに設定します\0
。ファイルにこれらの文字がないので、awk
内容全体をすぐに読みます。
答え2
これを機能させるための最小限の変更は次のとおりです。
cat file | awk '/mark:/{printf( "%s\n",gensub(/^.*mark: ([0-9]+).*$/,"\\1","g"))}'
/mark:/ は "mark:" を含む行を選択します。
しかし、なぜprintfが必要ですか?これはまた働きます:
cat file | awk '/mark:/{print(gensub(/^.*mark: ([0-9]+).*$/,"\\1","g"))}'
しかしそれは」猫の無駄な使用awkはファイルから直接読み取ることができるからです。
awk '/mark:/{print(gensub(/^.*mark: ([0-9]+).*$/,"\\1","g"))}' file
編集する:
ユーザー要求ごと:ファイルと文字列に正規表現を使用する方法。
まあ、あなたが設定したルールによると:gensubだけを使うawkでは不可能です。
また、一致の概念は、.*mark: ([0-9]+).*
すべてを括弧内の一致に置き換えることです。つまり、一部を抽出するにはファイル全体を一致させる必要があります。これがgrepが作成された理由の1つです。
ちょうど使用:
grep -oP "mark: \K([0-9]+)" file
または:
echo "$string" | grep -oP "mark: \K([0-9]+)"
あなたは結果を得るでしょう。