我有一系列文件,根据编号(File1.txt,File2.txt,File3.txt等)排序,我在自己的脚本中运行一个循环作为awk代码的输入。我可以将这些匹配为
awk ... file[1-$i].txt >> output
但是我想排除该范围内的文件,例如
file$v.txt
我正在寻找类似的东西
awk ... file[1-!$v-$i].txt >> output
我在其中匹配1- $ i中的每个文件,用$ v跳过该文件。
我已经按照here的描述尝试了来自复合模式匹配的各种输入,但是我无法获得适合我的语法。
有人知道怎么做这样的复合模式匹配吗?谢谢。
根据要求,这是我的文件:
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
此代码执行以下操作:
在this question中询问了我想做的一个简单示例,这是我从中获取awk代码的地方。
我的目标是在输出中包含以下行:
33.679538 0.249302
在其他正确匹配的行中,但这是我当前的测试,以查看它是否有效。现在,我有:
33.679538 0.378012
由于在awk代码中将file.4.dat添加到自身中,因为我无法在输入文件的第二个参数中排除它。
我的awk代码正在读取我所有的输入文件,并且需要排除其中的一个文件才能获得正确的输出。
最终,我必须分别输入我的5个文件中的每个文件与上述awk代码中的其他4个文件。将来,文件的数量将是可变的,因此我不能只在脚本中键入文件名。现在,如果我至少可以解决少于10个文件的问题,那将是一个很大的帮助。
答案 0 :(得分:2)
您只需在awk
中执行此操作,方法是识别要用作参考的第一个文件,而忽略使用nextfile
选项(需要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想知道他们是否可以构建可从Shell生成并使用的文件名模式列表。可以这样做,但是考虑到nextfile
中相对简单的选项,这看起来可能很复杂。
据您了解,您有n
个文件,其中一个将用作参考文件。我希望使用bash
外壳程序的extglob功能包括除引用之外的所有文件。例如我正在创建文件file1..10
来解释这一点
touch file{1..10}
exclude=3
扩展的shell选项是使用内置的shopt
设置的
shopt -s extglob
list=(!(file"$exclude"))
现在使用declare -p list
打印数组以查看仅排除参考文件的文件列表。现在,如下使用awk
中的数组。数组扩展"${list[@]}"
会导致排除上面生成的所有文件。
awk ... file"$exclude" "${list[@]}"
答案 1 :(得分:1)
要跳过文件,只需将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
或者,如果您愿意,可以按名称而不是arg列表中的顺序删除“坏”文件。
$ 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
答案 2 :(得分:0)
如果某人不想使用或系统中没有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
用于跳过所有其他语句)
答案 3 :(得分:0)
使用流水线awks。您必须提供最后一个文件作为参考(此处-> 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
$