既存の gawk ワンライナーは本当に近いです。ここでは、より読みやすいスクリプトとしてフォーマットされています。
FNR == 1 {
if (o)
close(o)
o = FILENAME
sub(/\.txt/, "_oddlines.txt", o)
}
{
NR % 2 == 1
print > o
}
これにより、エラーが明らかになるはずです1。したがって、そのエラーを削除します。
FNR == 1 {
if (o)
close(o)
o = FILENAME
sub(/\.txt/, "_oddlines.txt", o)
}
NR % 2 == 1 {
print > o
}
$ awk -f foo.awk *.txt
そしてそれは機能します(もちろん、これを再1行化できます)。
(通常、私はfor
他の回答と同じようにこれを行いますが、あなたがどれだけ近いかを見せたかったのです!)
1コメントごとに、あまり明白ではないかもしれません?
Awk の基本的な言語構造は、「パターン アクション」ステートメントです。awkプログラムは、そのようなステートメントの単なるリストです。「パターン」の名前は、もともとほとんどが grep のような正規表現パターンだったためです。
$ awk '/^be.*st$/' < /usr/share/dict/web2
beanfeast
beast
[snip]
(スラッシュを除いて、これは基本的に単に runningです。grep
これは、デフォルトのアクション を使用するためですprint
。)
パターンには実際には 2 つのアドレスを含めることができますが、これらの場合のように 1 つを使用する方が一般的です。スラッシュで囲まれていないパターンでは、 FNR == 1
(ファイルF
固有N
のこのR
レコードの数が等しい1
) またはNR % 2 == 1
(N
このR
レコードの数 - すべてのファイルで累積! - mod2
が等しい1
) のようなテストが可能です。
ただし、開き括弧を押すと、「アクション」部分に入ります。NR % 2 == 1
単純に結果 (true または false) を計算し、それを破棄します。「パターン」部分を完全に省略すると、「アクション」部分がすべての入力行で実行されます。したがって、これはすべての行を出力します。
NR % 2 == 1
テストは累積レコード番号をテストしていることに注意してください。したがって、あるファイルの行数 (「レコード」) が奇数の場合、次のファイルは偶数行ごとに出力されます (これは、行数が奇数の別のファイルにヒットするまで持続します)。
たとえば、2 つの入力ファイルがA.txt
と であるとしB.txt
ます。awk は読み取りを開始し、最初の行で と のA.txt
両方FNR
を1 に設定します。最初の「アクション」が行われるので、設定. 次に、awk は 2 番目のパターンをテストします。 は 1 です。したがって、2 番目の「アクション」が実行され、その行が に出力されます。NR
file A, line 1
FNR == 1
o
NR
NR % 2
A_oddlines.txt
ここで、ファイルA.txt
にその 1 行だけが含まれているとします。awk は file に進みB.txt
、リセットしますが、累積的なFNR
ままになります。NR
の最初の行B
はfile B, line 1
. Awk は最初の「パターン」を試行します。実際、FNR == 1
これにより古いパターンが閉じo
られ、新しいパターンが設定されます。
しかし、NR
はすべての入力ファイルにわたって累積さ2
れるためです。そのため、2 番目のパターン ( )は (どちらが であるか) を計算し、どちらが false であるかを比較するため、awk は file の 1 行目の 2 番目の「アクション」をスキップします。行 2 が存在する場合は、andがあるため、その行がコピーされます。NR
NR % 2 == 1
2 % 2
0
== 1
B.txt
FNR == 2
NR == 3
(私は当初、あなたのスクリプトがほぼ機能していたので、これを意図していて、構文に少し固執しているだけだと思っていました。)