将多个文件与数字匹配,并按数字排除一个文件之一

  • 本文关键字:数字 文件 排除 一个 bash awk
  • 更新时间 :
  • 英文 :


i有一系列文件,根据编号(file1.txt,file2.txt,file3.txt等)进行排序尴尬代码的输入。我可以将它们匹配为

awk ... file[1-$i].txt >> output

我想在该范围内排除文件,例如

file$v.txt

目标

我正在寻找

之类的东西
awk ... file[1-!$v-$i].txt >> output

我从1- $ i匹配每个文件的地方,用$ v跳过文件。


我尝试了此处所述的复合模式匹配的各种输入,但是我无法让语法为我工作。

有人知道如何进行复合模式匹配吗?谢谢。


样品输入

应要求,这是我的文件:

file.1.dat

29.078306 0.00676358
29.223592 0.00309192
30.297306 0.0174575
30.478883 0.132458
30.503705 0.118951
30.512891 0.0705088
31.945900 0.00408244
32.321011 0.00258023
32.894037 0.00407912
32.916263 0.00330154
34.594139 0.00874524
34.849178 0.0195172
34.884655 0.00547378
34.967403 0.00308369
35.325397 0.00818193

file.2.dat

25.970535 0.0979715
26.913976 0.00593039
29.078306 0.0984052
29.223592 0.00271504
30.236632 0.013818
30.478883 0.0347606
30.503705 0.102369
30.512891 0.0409633
31.714064 0.0242958
31.902306 0.0510168
32.715764 0.0146584
34.952965 0.00484555
35.190790 0.0114201
35.360372 0.0033089
35.575199 0.00282864
38.184618 0.00551692

file.3.dat

31.591771 0.0126916
32.059389 0.0605918
32.299959 0.122618
32.890418 0.0058495
32.962536 0.00492958
33.646214 0.0705359
33.679538 0.120592

file.4.dat

25.636267 0.00398174
27.848542 0.00485739
28.269278 0.0174401
29.418886 0.00409613
31.313212 0.203932
31.945900 0.00259743
32.256620 0.00325607
32.299959 0.0325366
33.461363 0.0798633
33.646214 0.0516498
33.679538 0.12871

file.5.dat

29.767600 0.00777448
32.299959 0.00777995
34.849178 0.0305844
34.884655 0.0126815
34.930799 0.0546924
34.952965 0.0711241

尴尬代码

awk '
NR==FNR {
    a[$1]=$2
    next
}
($1 in a) {
    a[$1]+=$2
}
END {
    for(i in a)
        print i,a[i]
}' file.4.dat file.[1-5].dat >| test.out

此代码执行以下操作:

  1. 匹配文件。
  2. 在找到$ 1中的匹配时,它将添加$ 2的文件。4。dat $ 2在匹配行中。
  3. test.out打印文件。

在这个问题中问了一个简单的示例,这是我从中获得尴尬代码的地方。

目标

我的目标是在我的输出中有以下行:

33.679538 0.249302

除其他正确匹配的线路外,但是这条线是我当前的测试,以查看它是否有效。现在,我有:

33.679538 0.378012

由于file.4.dat在awk代码中添加到自身,因为我不能在输入文件的第二个参数中排除它。

问题摘要

我的尴尬代码正在读取我的所有输入文件,我需要排除1个文件以获取正确的输出。

最终,我必须针对上面的awk代码中的其他4个文件分别输入我的5个文件中的每个文件。将来,文件数将是可变的,因此我不能仅在脚本中输入文件名。目前,如果我至少可以以不到10个文件解决此问题,那将是一个主要的帮助。

您可以在awk中简单地执行此操作,通过识别您使用的第一个文件,并忽略使用nextfile选项(需要GNU版本)的后续处理(需要GNU版本),该文件跳过处理文件以进行后续文件处理文件加工。通过此逻辑,您应该放置参考文件,例如 file.4.dat在您的输入中作为文件列表中的第一个参数。

awk '
BEGIN{ ignoreFile = ARGV[1] }
NR==FNR {
    a[$1]=$2
    next
}
FILENAME == ignoreFile { nextfile }
($1 in a) {
    a[$1]+=$2
}
END {
    for(i in a)
        print i,a[i]
}' file.4.dat file.[1-5].dat >| test.out

op想知道他们是否可以构建可以从外壳生成并使用的文件名的模式列表。可以完成,但是考虑到nextfile可用的相对简单的选项,这看起来可能很复杂。

根据您的理解,您有n文件,其中一个将用作参考文件。我更希望使用bash Shell的ExtGlob功能包括除了参考之外的所有文件。例如我正在创建文件file1..10用于解释此

touch file{1..10}
exclude=3

使用shopt内置

设置了扩展的外壳选项
shopt -s extglob
list=(!(file"$exclude"))

现在,使用declare -p list打印数组,以查看仅包括参考文件的文件列表。现在,如下所示,使用awk中的数组。数组扩展"${list[@]}"导致您在上面生成的所有文件。

awk ... file"$exclude" "${list[@]}"

要跳过一个文件,您将ARGV[its position in the arg list]设置为null。例如:

$ ls
file1  file2  file3
$ grep . file*
file1:x
file2:y
file3:z
$ awk 'BEGIN{ARGV[2]=""} {print FILENAME, $0}' file*
file1 x
file3 z

或者,如果您喜欢:

$ awk 'BEGIN{for (i in ARGV) if (ARGV[i]=="file2") ARGV[i]=""} {print FILENAME, $0}' file*
file1 x
file3 z
$ awk 'BEGIN{bad["file2"]; for (i in ARGV) if (ARGV[i] in bad) ARGV[i]=""} {print FILENAME, $0}' file*
file1 x
file3 z
$ awk '
    BEGIN {
        split("file2 file3",tmp); for (i in tmp) bad[tmp[i]]
        for (i in ARGV) if (ARGV[i] in bad) ARGV[i]=""
    }
    {print FILENAME, $0}
' file*
file1 x

如果某人不想使用或在其系统中没有nextfile,则跟随可以帮助您。

awk -v ignore="file.4.dat" '
FNR==1{
    no_parse=""
}
FNR==NR {
    a[$1]=$2
    next
}
FILENAME == ignore{
    no_parse=1
}
no_parse{
    next
}
($1 in a) {
    a[$1]+=$2
}
END {
    for(i in a)
        print i,a[i]
}' file.4.dat file.[1-5].dat >| test.out

创建了一个名为 ignore的变量,我们可以提及input_file,我们需要忽略该变量,一旦input_file转弯来解析,我已经将名为 no_parse的标志设置为true,在这种情况下,特定input_file的内容将被读取(因为next用于跳过所有其他语句)

使用管道上的尴尬。您必须将最后一个文件作为参考(以下 -> 4)

awk ' $(NF+1)=FILENAME' file.[1-3].dat file.5.dat file.4.dat |  
   awk ' { a[$1]+=$2; $2=a[$1] } /file.4.dat/ && NF-- '

给定文件

$ awk ' $(NF+1)=FILENAME' file.[1-3].dat file.5.dat file.4.dat |  
      awk ' { a[$1]+=$2; $2=a[$1] } /file.4.dat/ && NF-- '
25.636267 0.00398174
27.848542 0.00485739
28.269278 0.0174401
29.418886 0.00409613
31.313212 0.203932
31.945900 0.00667987
32.256620 0.00325607
32.299959 0.162935
33.461363 0.0798633
33.646214 0.122186
33.679538 0.249302
$

相关内容

  • 没有找到相关文章

最新更新