
grep
、、などの他のツールを使用して複数のawk
パイプを一致させた後に直接行を印刷するコマンドがありますtail
。これはうまくいきますが、少し汚れていて、これを行うためにいくつかのパイプを使用しています。これらのツールの1つを使用して、1つのコマンドでこれを実行できますか?ファイルの末尾に空白行もあります。
文書の内容:
10:28:48 2022-09-15T15:28:36Z: Creating tar ball for build artifacts
--
10:28:53 --> Build complete: Artifacts were created:
file: build-1.tar.gz
注文する
grep -A1 "Artifacts were created:" $file | tail -n1 | awk '{print $2}'
結果
build-1.tar.gz
これは技術的には可能ですが、やや混乱しているようです。
答え1
試してみてください:
awk '/Artifacts were created:/{p=1} NF{out=$2} END{if(p==1){print out}}' infile
指定したパイプラインは、最後のフィールドではなく一致後の行の2番目のフィールドを抽出しています。これはawkへの単一の呼び出しに変換されます。
awk '
# Have we found the match?
/Artifacts were created:/{ found=1 ; next }
# if a match has been found, print and exit
found == 1 { print $2; exit }
' "$file"
答え2
sed
オプションなら
$ sed -En '/Artifacts were created:/{n;s/[^ ]* (.*)/\1/p}' <<< "$file"
build-1.tar.gz
答え3
これオリジナルリクエスト一致後に空でない最後の行の値を要求します。ここで一致するトリガーが見つかったら、フラグを設定してください。フラグを設定した後、ファイルが終了するのを待ってから、キャプチャした最後の項目を印刷します。
awk '
# Set the flag on match
/Artifacts were created/ { flag++ }
# Capture second field of a line that is not just whitespace
NF { lastitem = $2 }
# At the end, maybe print the last captured item
END { if (flag) { print lastitem } }
' "$file"
一部のバージョンでは、句の最後の部分を引用することがawk
できます。ここでは、ファイルを閲覧するときに最新のアイテムをキャプチャするより直接的なアプローチを好みます。$2
END
更新された要件では、一致の直後の行に値を指定する必要があります。ファイルを完全に処理する必要がないため、これははるかに簡単で高速です。
awk '
# Output second field of line immediately following the flag being set
flag && NF { print $2; exit }
# Set the flag on match
/Artifacts were created/ { flag++ }
' "$file"
答え4
使用幸せ(以前のPerl_6)
~$ raku -e 'put $<>.words[1] if m{ "Artifacts were created:" \n <( \N* } for lines.join: "\n";' file
#OR
~$ raku -e 'put $0.words[1] if m{ "Artifacts were created:" \n (\N*) } for lines.join: "\n";' file
OPがPerlプログラミング言語スイートを喜んで考えるなら、Rakuは良い選択です。上記では、入力ファイルを1行ずつ読み、\n
改行文字で連結します。ターゲットを識別し、"Artifacts were created:" \n
一致するものを見つけます。
最初の例では、Rakuのキャプチャタグは一致<( … )>
オブジェクトから "Artifacts ..."行を削除するために使用され、キャプチャされた.words[1]
2番目のスペースで区切られたフィールドは一致変数と共に使用(または同義語)されput
ます(条件付き出力にによって異なります)。 。実際、この問題にはキャプチャタグが1つだけ必要です。$<>
$/
if
<(
2番目の例では、括弧を使用して一致の一部を$<>.[0]
match-variableと同じ$/.[0]
match-variableとしてキャプチャします$0
。キャプチャされた.words[1]
2番目のスペースで区切られたフィールド$0
には条件がput
適用されますif
。
入力例:
10:28:48 2022-09-15T15:28:36Z: Creating tar ball for build artifacts
--
10:28:53 --> Build complete: Artifacts were created:
file: build-1.tar.gz
出力例:
build-1.tar.gz
Rakuには実際にはかなり多くの組み込み文字クラスがあるので、[\N* \n]
特徴的なパターン(ゼロ以上の非改行文字の後に改行文字が続くもの)を他の多くのパターン(または[\S* \s]
など[\d* \D]
)にコピーできます。