如果数据可用,如何获取文件名

如果数据可用,如何获取文件名

我的输入文件是file_1.txtfile_2.txtfile_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。下面是你真正应该如何做你的问题中的 shell 脚本所做的事情(我能说的最好的),在每个 Unix 机器上的任何 shell 中使用任何 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中的以下评论:如果您不希望将其存储在单独的文件中,则以下是如何在shell脚本中内联使用上述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
    }
' "${@:--}"

然后你可以将 shell 脚本称为:

$ ./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

行的分解:

  • 调用 sed 时不带自动打印 (-n) 选项,因为我们对快速打印模式不感兴趣,而只对文件名感兴趣。
  • 使用单独的流 (-s) 选项调用 sed。通常 sed 将所有文件视为一个流。
  • 假设数据行不能包含 # 字符,我们连接下一行并检查它是否非空。在这种情况下,使用 F 命令打印当前文件名。
  • 第二个 sed 打印 _ 和点之间的字符串。

相关内容