awkで1行の処理を停止する方法はありますか?アクション内の制御構造ではなく、パターンとアクションのペアで動作するようなものはbreak
ありますか?continue
次のファイルがあり、各名前を、、、、input.txt
に変更しようとしているとします。しかし、空白で始まるか、単独で始まる行を残したいと思います。x0
x1
x2
...
-
-- data
bob 4
joe 5
bob 6
joe 7
になる:
-- data
x0 4
x1 5
x0 6
x1 7
これを行うための次のスクリプトがあります。 (しかし、文字列リテラルの代わりに区切り文字を使用してこれを構成するより良い方法があるかもしれません。)
#!/bin/sh
awk '
BEGIN { c = 0; }
# do not process lines beginning with - or space
/^[- ]/ {
print;
}
# update
/^[^- ]/ {
if (! ($1 in name) ) {
new_name = "x" c;
c += 1;
name[$1] = new_name;
}
$1 = name[$1];
print;
}
' input.txt
このスクリプトにはいくつかの欠点があります。まず、私たちは相互に排他的であることを知っていますが、/^[- ]/
その/^[^- ]/
財産はどこにも適用されません。break
最初の一致後に行処理を放棄するなどの機能を使用できることを願っています。
/^[- ]/ {
print;
break;
}
最初の2つのパターンのいずれにも一致しない空でない行がある場合は、問題があることをユーザーに警告するために別の句を追加できるようにしたいです。
/./ {
print "non-empty line!" > "/dev/stderr"
# or print "non-empty line!" > "/dev/tty" if portability is a concern
}
ただし、このパターン操作のペアをそのままスクリプトに追加すると、空でないすべての行の後に実行されます。
行が「成功的に」処理されたので、その行の処理を停止するために最初の2つのテストケースの後に追加できるものはありますか?これが不可能な場合、包括的な状況を処理するための一般的なawkイディオムはありますか?
答え1
このawk
ステートメントを使用して、next
次の入力レコードの処理をすぐに続行できます。
以下はスクリプトの代替実装ですawk
。
awk '/^[- ]/ { print; next } !($1 in n) { n[$1] = sprintf("x%d", c++) } { $1 = n[$1]; print }' data.in
コードawk
は
/^[- ]/ { print; next }
!($1 in n) { n[$1] = sprintf("x%d", c++) }
{ $1 = n[$1]; print }
c
カウンターです。最初からゼロでした。
n
新しいタグ/名前を保持する連想配列。索引付けには、ファイルの最初のフィールド/列のデータを使用します。
!($1 in n)
最初のフィールドのデータにまだ新しいラベル/名前が割り当てられていない場合はtrue。