我有一个文件ff.txt,如下所示
*ABNA.txt
356
24
36
112
*AC24.txt
457
458
321
2
ABNA.txt和AC24.txt是名为foo1的文件夹中的文件。根据ff.txt文件中的数字,我想从foo1文件夹中的相应文件中提取行,并使用另一个文件夹foo2中的现有文件名创建新文件。 如果ABNA.txt文件的第三列或第四列包含356,24,36,112个数字,请提取该行并将其另存为另一个文件夹foo2,如ABNA.txt。
文件夹foo1中的ABNA.txt文件如下所示
dfg qza 356 245
hjb hkg 455 24
ghf qza 12 123
dfg qza 36 55
文件夹foo1中的AC24.txt文件如下所示
hjb hkg 457 167
ghf qza 2 165
sar sar 234 321
dfg qza 345 345
输出:
文件夹foo2中的ABNA.txt文件
dfg qza 356 245
hjb hkg 455 24
dfg qza 36 55
文件夹foo2中的AC24.txt文件
hjb hkg 457 167
ghf qza 2 165
sar sar 234 321
你的帮助将不胜感激!
答案 0 :(得分:1)
<强>已更新强>
这是一个纯粹的bash
解决方案(grep
已删除):
#!/bin/bash
file=
s=()
grp() { r="${s[@]}";r="\b("${r// /|}")\b";
while read w; do [[ $w =~ $r ]] && echo $w;done <foo1/$file >foo2/$file
}
while read a; do
if [[ $a =~ ^\* ]]; then
[ -n "$file" ] && grp
file=${a#\*}
s=()
else s=(${s[@]} $a)
fi
done < ff.txt
[ -n "$file" ] && grp
#See input and output files
for i in foo1/*;{ echo %% in $i; cat $i;}
for i in foo2/*;{ echo %% out $i; cat $i;}
输出
%% in foo1/ABNA.txt
dfg qza 356 245
hjb hkg 455 24
ghf qza 12 123
dfg qza 36 55
%% in foo1/AC24.txt
hjb hkg 457 167
ghf qza 2 165
sar sar 234 321
dfg qza 345 345
%% out foo2/ABNA.txt
dfg qza 356 245
hjb hkg 455 24
dfg qza 36 55
%% out foo2/AC24.txt
hjb hkg 457 167
ghf qza 2 165
sar sar 234 321
在while循环中,它解析ff.txt
文件。如果一行以*
开头,则设置file
环境变量。如果不是以*
开头,则它是一个数字并添加到s
数组中。如果找到一个新的文件名并且有一个旧的文件名集,那么它会调用grp
函数来完成实际的工作。
函数grp
以\b(num1|num2...)\b
格式创建正则表达式。 \b
仅匹配完整的数字。因此\b24\b
与245
不匹配。 while循环从foo1
读取文件,将每一行与正则表达式匹配,并将具有相同名称的文件写入目录foo2
。它不检查是否存在foo2
目录。
答案 1 :(得分:1)
这可能适合你(GNU sed和Bash):
folder1=foo1
folder2=foo2
sed -r '/^\*/!{s/\s*//g;H;$!d};1{h;d};x;s/\n/ /;s/\n/|/g;s#\*(.*) (.*)#<'"$folder1"'/\1 sed -nr '\''/^(\\S+\\s+){2,3}\\b(\2)\\b/w '"$folder2"'/\1'\''#' ff.txt | sh
这会将ff.txt
文件转换为通过管道传递到sh
命令的脚本。用户必须首先将bash变量$folder1
和$folder2
分别设置到包含源文件和输出文件的目录中。
答案 2 :(得分:1)
你可以尝试这样的事情 -
awk '
BEGIN {
readpath=sprintf("%s", "/path/to/foo1")
writepath=sprintf("%s", "/path/to/foo2")
}
$0~/\*/ {
file = substr($1,2)
while ((getline var < (readpath"/"file)) > 0) {
split (var, a, " ")
ary[a[3]]=var
ary[a[4]]=var
}
}
($1 in ary) {
print ary[$1] > (writepath"/"file)
}' foo.txt
[jaypal:~/temp/test] ls
foo.txt foo1 foo2
[jaypal:~/temp/test] cat foo.txt
*ABNA.txt
356
24
36
112
*AC24.txt
457
458
321
2
[jaypal:~/temp/test] ls foo1/
ABNA.txt AC24.txt
[jaypal:~/temp/test] head foo1/*
==> foo1/ABNA.txt <==
dfg qza 356 245
hjb hkg 455 24
ghf qza 12 123
dfg qza 36 55
==> foo1/AC24.txt <==
hjb hkg 457 167
ghf qza 2 165
sar sar 234 321
dfg qza 345 345
[jaypal:~/temp/test] ls foo2/
[jaypal:~/temp/test]
[jaypal:~/temp/test] awk '
BEGIN {
readpath=sprintf("%s", "./foo1")
writepath=sprintf("%s", "./foo2")
}
$0~/\*/ {
file = substr($1,2)
while ((getline var < (readpath"/"file)) > 0) {
split (var, a, " ")
ary[a[3]]=var
ary[a[4]]=var
}
}
($1 in ary) {
print ary[$1] > (writepath"/"file)
}' foo.txt
[jaypal:~/temp/test] ls foo2/
ABNA.txt AC24.txt
[jaypal:~/temp/test] head foo2/*
==> foo2/ABNA.txt <==
dfg qza 356 245
hjb hkg 455 24
dfg qza 36 55
==> foo2/AC24.txt <==
hjb hkg 457 167
sar sar 234 321
ghf qza 2 165
答案 3 :(得分:1)
#!/bin/bash
mkdir -p foo2
awk '
function process_file(filename, values, filein, fileout, line, f) {
if (filename == "") return
filein = "./foo1/" filename
fileout = "./foo2/" filename
while ((getline line < filein) > 0) {
split(line, f)
if (f[3] in values || f[4] in values) {
print line > fileout
}
}
}
/^\*/ {
process_file(filename, values)
filename = substr($0, 2)
delete values
next
}
{ values[$1] }
END { process_file(filename, values) }
' ff.txt