FSの正規表現がspace-open_parenthersisまたはopening_parenesis-coma-spaceに設定されていると、gawk操作に問題があります。いくつかのアプローチを試しましたが、それらのどれも予想される動作につながりませんでした。FS="( ()|(), )"
第二。FS="[( ()(), )]"
番号3(ASCII OCTコードを使用)FS="[(\040\050)(\051\054\040)]"
番号4FS="((\040\050)|(\051\054\040))"
私の入力ファイルは次のとおりですhttps://phpaste.sourceforge.io/demo/paste.php?id=144これは、Debianのapt-getログの1つのレコード(行)のみを含み、いくつかのパッケージを一覧表示するファイルです。
私のgawkプログラムは次のとおりです
#! /usr/bin/gawk -f
BEGIN {FS = "[(\040\050)(\051\054\040]"}
{
for(i=1;i<=NF;i=i+2) #I increased i by 2 because i want to print the odd numbered fields(only the names of the packages:architecture)
print $i
}`
bashで実行します。myawk.awk input.txt > output.txt
ここにFXXXという大きな単語を追加したい! ! ! !今解決しました。引き続き努力したことに対する報酬だと思います。私はこの方法を使用しましたが、なぜASCII 8進コードの前に3つのバックスラッシュがあるのかFS = "(\\s\\\050)|(\\\051,\\s)"
よくわかりませんでした。\\\
誰でもこれについて説明を提供できますか?なぜですか? ?私はAWKが正規表現を2回読むことを読んでいましたが、これは必須ですが、\\
私はそれが必要です\\\
(3回!!!)。
代替案や他のアプローチも大いに感謝します!
よろしくお願いします!
これが私が望んだ結果であり、ありがたいことに前回の実行から得られました。https://phpaste.sourceforge.io/demo/paste.php?id=145(アーキテクチャを含むパッケージのリスト)
答え1
あなたはこれを過度に考えているかもしれません。少し。私はそれを動作させ、FS=" \\(|\\), "
さらにそれをFS=" \\(|), "
。
- あなたはそれをしなければならないと信じているように見えますが、実際にあなたがしなければならないことはそれだけです。
"(regex1)|(regex2)"
"regex1|regex2"
- 括弧をグループ化括弧の中に入れると、内部括弧が文字通りのテキスト括弧になると思うようです。しかし、実際にはそうではありません。正規表現のグループ化は入れ子にすることができます。角かっこをリテラルテキスト角かっことして扱うには、それをエスケープする必要があります。
)
グループ内の正規表現内でのみ特別です。(
エスケープされている場合は、)
エスケープは必要ありません。
これがトリッキーになるところです。無邪気に言えば、上から見れば十分FS=" \(|), "
でしょう。しかし、GAWKには文字列定数の正規表現に問題があります。GNU Awkユーザーガイド、セクション9.1.3.1。&
、またはによって呼び出される代替テキストからテキストを取得することに焦点を当てていますが、以下でも機能しているようです。sub()
gsub()
gensub()
FS
...いくつかのレベルがありますエスケープ処理進行中です。
まず、次のようなものがあります。語彙レベル、
awk
プログラムを読み込み、実行のために内部コピーを作成するのにかかる時間です。そして、awk
[プログラムが実際にスキャンされ実行される方法を決定する]ランタイムレベルがあります。両方のレベルで
awk
バックスラッシュの後に表示される可能性のある定義された文字セットを見つけます。語彙レベルでリストされたエスケープシーケンスを見つけます。エスケープシーケンス。 したがって、awk
ランタイムレベルで処理されるすべての「\」に対して、語彙レベルで2つのバックスラッシュを入力する必要があります。 …
強調が追加されました(最後の文章)。これはFS
(" \(|), "
左角かっこをエスケープし、角かっこをリテラル、リテラル角括弧として扱う)に設定するには、次のものが必要であることを意味するようです。分配する FS=" \\(|), "
または、指定された-F' \\(|), '
(エスケープされたバックスラッシュ)簡単なテストでこれを確認できます。実行し、awk -F' \\(|), '
プログラムFS
から印刷します。と表示されます \(|),
。
通常、特殊文字を特殊文字以外の文字に変換したい場合(またはその逆に変換したい場合)、一般的なレガシーアプローチは\
(バックスラッシュ)を使用してエスケープすることです。しかし、正規表現に関連する別のメカニズムがあります。まさに式の使用です[…]
。[…]
式の唯一の特殊文字は^
、-
そして]
(場所に応じて)。
[pq]
p
一つまたは一つを意味するq
[()]
(
一つまたは一つを意味する)
[(p]
(
一つまたは一つを意味するp
[(]
a(
または...まあ、他の文字がないので、テキストだけを意味します(
。
したがって、バックスラッシュにアレルギーがある場合に設定できますFS=" [(]|), "
。
答え2
私が思いついた別の方法があります。出力と正確に一致します。split()
各項目に対する追加の操作により効率が低下する可能性がありますが、読みやすく理解しやすくなります。
#!/usr/bin/awk -f
BEGIN {
FS="), "
}
{
sub(/^Install:/, "")
for (i=1; i<=NF; i++) {
split($i, a, " ")
print a[1]
}
}
答え3
awkを使わずに同じことをするより簡単な方法があります。主要なLinuxディストリビューションで利用可能なさまざまなバージョンのgrepでPerl正規表現を使用できます。私のgrepバージョン(GNU grepバージョン2.27)では、以下はawkソリューションと同じ出力を提供します。
grep -oP '(?<=\),).*?(?=\()' input.txt > output.txt