tac コマンドのオプションにより奇妙な出力が生成される

tac コマンドのオプションにより奇妙な出力が生成される

このファイルには何も入っていないとします

a
b
c
b
a

tac --separator=a fileBASH [Debian ベースの Linux 上] で使用すると、次のようになります。

                  # empty line
                  # empty line
b
c
b
aacommand@prompt  # two a just before the prompt


質問: 私の理解では、ではなく が文字列内の区切りをマークする--separator=aことを定義します。anewlineこれは正しいですか?

私はこれを他の文字列やもっと多くの入力で試してみましたが、かなり混乱した状態になりました。他のオプションはすべて正常に動作すると思います。私が使用した場合、tac --before最初に 1 行よりも 5 行ほどの空白行が表示されますが、その後はこれくらいで済むはずですよね?

答え1

tac主に設計されているケース、つまりセパレータがレコード ターミネータである場合、つまりセパレータが最後のレコードの後に​​表示される場合、の方が理解しやすくなります。レコード (各ターミネータを含む) は逆の順序で印刷されます。

$ echo -n fooabara | tac -s a; echo
rabafooa

入力は 3 つのレコード ( foobおよびr) で構成され、各レコードの後に​​セパレータ が続きます。a出力は 3 つのレコード ( rbおよびfoo) で構成され、各レコードの後に​​セパレータ が続きますa

最後のレコードがレコード ターミネータで終わらない場合は、レコード セパレータなしで最初に印刷されます。

$ echo -n fooabar | tac -s a; echo
rbafooa

最後のレコードrの末尾に区切り文字がなかったため、最後のbレコードは、間に区切り文字が入らない状態で最後から 2 番目のレコードと連結されます。

改行があるため、入力が少しわかりにくくなっています。改行の代わりにカンマを使用して見てみましょう。

$ echo -n a,b,c,b,a, | tac -s a; echo
,,b,c,b,aa

入力レコードは 3 つあります。空のレコード (ターミネータ付きa)、かさばるレコード,,b,c,b,(これもターミネータ付き)、および,末尾の未終了のレコードです。これらのレコード (ターミネータのない最後のレコードを除き、それぞれにターミネータ付き) は逆の順序で印刷されます。

おそらく、あなたの混乱は「セパレータ」がセパレータであると期待していることから来ているのでしょうが、これは誤った名称です。これは実際にはレコード ターミネータです。--before代わりにイニシエーターになります。

答え2

次の例は、--regexオプションの使用に役立つ場合があります。

$ cat records 
---1---
1
2
3
---2
A
B
C
---3--
a
b
c
$ tac --before --regex --separator=^---[0-9]+-*$ records
---3--
a
b
c
---2
A
B
C
---1---
1
2
3

この例では、ファイルにはrecords複数行のレコードが含まれており、各レコードは で始まる行 ( ^...$) で始まり---、その後に数字 ( [0-9]+) とオプションのマイナス記号のシーケンス ( -*) が続きます。各レコードの行の順序とそのヘッダー行が保持されていることがわかります。

私はtac、Twitter などのフィード アプリケーションで使用されるように、ログ ファイルのエントリを逆順に表示するためにこの方法を使用します。たとえば、最後の 2 つのレコードのみを逆順に印刷するには、次のようにします。

tac --before --regex --separator=^---[0-9]+-*$ example \
 | awk '/^---[0-9]+-*$/ {c++} c>2 {exit}{print}'

関連情報