私の入力ファイルはfile_1.txt
、、、file_2.txt
などfile_3.txt
です。このファイルには次のデータが含まれています
$ head log_file_reset_*.txt
==> file_1.txt <==
Test #1
data
Test #2
data
Test #3
Test #4
data
==> file_2.txt <==
Test #1
Test #2
data
Test #3
Test #4
data
==> file_3.txt <==
Test #1
data
Test #2
data
Test #3
Test #4
Test
今持っているコードは、入力ファイルの各データの下に使用可能なデータが次の場合にのみ、後続のシリアル番号を取得できます。Test
#!/bin/bash
#################################################################################################
CWD=$(pwd)
for j in {1..5}
do
sed -n '
/^Test #/ {
s///
=
p
}
$=
' file_$j.txt \
| paste - - \
| awk -F '\t' '
NR > 1 && $1 - prevLine > ($2 ? 2 : 0) {print prev}
{prevLine = $1; prev = $2}
' >> 1_val.txt
このコードから得られた出力は、次の場所に保存されます1_val.txt
。
1_val.txt
1
2
4
2
4
1
2
リストされたデータのファイル名(数字のみ)を取得し、名前1_val.txt
が別のファイルに保存されるようにコードを変更する方法を知ることができますか2_val.txt
?
予想出力:
2_val.txt
1
1
1
2
2
3
3
答え1
awkを使用すると、sedは必要ありません。すべてのUnixシステムのすべてのシェルでawkを使用して、質問のシェルスクリプトが実行するアクションを実際に実行する方法は次のとおりです。
$ cat tst.awk
FNR==1 {
testId = ""
}
testId != "" {
if (NF) {
print testId
}
testId = ""
}
sub(/^Test #/,"") {
testId = $0
}
$ awk -f tst.awk file_*.txt
1
2
4
2
4
5
1
2
次に、上記の内容を1つの出力ファイルに印刷し、ファイル番号を別の出力ファイルに印刷するには、次のように調整します。
$ cat tst.awk
FNR==1 {
testId = ""
split(FILENAME,f,/[_.]/)
fileId = f[2]
}
testId != "" {
if (NF) {
print testId > "1_val.txt"
print fileId > "2_val.txt"
}
testId = ""
}
sub(/^Test #/,"") {
testId = $0
}
$ awk -f tst.awk file_*.txt
$ head *_val.txt
==> 1_val.txt <==
1
2
4
2
4
5
1
2
==> 2_val.txt <==
1
1
1
2
2
2
3
3
OPの次のコメントを解決するために編集します。別のファイルに保存したくない場合は、シェルスクリプトで上記のawkスクリプトインラインを使用する方法は次のとおりです。
$ cat tst.sh
#!/usr/bin/env bash
awk '
FNR==1 {
testId = ""
split(FILENAME,f,/[_.]/)
fileId = f[2]
}
testId != "" {
if (NF) {
print testId > "1_val.txt"
print fileId > "2_val.txt"
}
testId = ""
}
sub(/^Test #/,"") {
testId = $0
}
' "${@:--}"
その後、シェルスクリプトを呼び出すことができます。
$ ./tst.sh file_*.txt
答え2
GNU sedがある場合は、次のようにできます。
sed -nsE '
/#/N;/\n./F
s/.*#([0-9]+)\n.+/\1/w1_val.txt
' file_?*.txt |
sed '/\n/P;y/_./\n\n/;D' > 2_val.txt
head [12]_val.txt
==> 1_val.txt <==
1
2
4
2
4
1
2
==> 2_val.txt <==
1
1
1
2
2
3
3
行分析:
- クイック印刷モードには興味がなく、ファイル名にのみ興味があるため、自動印刷(-n)オプションなしでsedを呼び出します。
- 別のストリーム(-s)オプションを使用してsedを呼び出します。通常、sedはすべてのファイルを1つのストリームとして扱います。
- データ行に#文字を含めることができないとし、次の行を連結して空でないことを確認します。この場合、F コマンドを使用して現在のファイル名を印刷します。
- 2 番目の sed は _ とドットの間の文字列を出力します。