データがある場合のファイル名の取得方法

データがある場合のファイル名の取得方法

私の入力ファイルは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 は _ とドットの間の文字列を出力します。

関連情報