出力の2行目で他のコマンドをどのように実行できますか?
たとえば、echo foo | sed p
どのような出力がありますか?
foo
foo
sed 's/foo/bar/'
私はそれらのいずれかを実行して取得したいと思います。
bar
foo
答え1
存在する
$ echo foo | sed p
foo
foo
最初のものはfoo
コマンドによって印刷されp
、2番目はパターンスペースがループの終わり(次の行を読む直前)に印刷される-n
ため、印刷されません。sed
foo
だからそれを取得するにはbar
:
$ echo foo | sed 'p;s/foo/bar/'
foo
bar
または:
$ echo foo | sed -n 'p;s/foo/bar/p'
foo
bar
bar
置換がある場合にのみ印刷します(s
置換が成功した場合はフラグ付きコマンドで)。p
bar
、を取得するには、元の元の行を取得し、foo
交換h
結果を印刷して復元します。
$ echo foo | sed 'h;s/foo/bar/p;g'
bar
foo
答え2
データの最初の行に影響を与えないコマンドを実行するには、サブシェルでそのコマンドを実行し、次のように最初の行を読み書きするコマンドを前に付けます。
read -r line; echo "$line" # pass first line unmodified
sed 's/foo/bar/' # operate on rest of lines
全体の例は次のとおりです。
$ echo foo | sed p | ( read -r line; echo "$line"; sed 's/foo/bar/')
foo
bar
答え3
入力行番号に応じて他の操作を実行できるコマンドにそれらをパイプすることをお勧めします。
たとえば、次のようになりますsed
。
$ printf 'foo\nfoo\n' | sed '2,$s/foo/bar/'
foo
bar
これは、sedのアドレス指定構文を使用して、操作を2行s/foo/bar/
からファイルの終わりまで()までの行に制限します。2,$
(man sed
GNUバージョン、より読みやすくフォーマットを少し変更しました):
Sedコマンドはアドレスなしで実行できます。この場合、コマンドはアドレスを持つすべての入力ラインで実行されます。この場合、コマンドはそのアドレスに一致する入力ラインでのみ実行されます。この場合、命令は、第1のアドレスから始まり第2のアドレスまで続くラインの包含範囲に一致する全ての入力ラインに対して実行される。
アドレス範囲について注意する3つの点は次のとおりです。
構文はaddr1、addr2です(つまり、カンマでアドレスを区切ります)。
addr2 が前の行を選択しても、addr1 と一致する行は常に許可されます。
addr2が正規表現の場合、addr1と一致する行はテストされません。
またはawk
:
$ printf 'foo\nfoo\n' | awk 'NR > 1 {gsub(/foo/,"bar")};1'
foo
bar
またはパール:
$ printf 'foo\nfoo\n' | perl -p -e 's/foo/bar/ if $. > 1'
foo
bar
awkとperlのバージョンは、行番号(NR
awkの場合、$.
perlの場合)が1より大きいかどうかをテストします。