1

我有一个文件 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 个数字,则提取这些行并将其作为 ABNA.txt 保存到另一个文件夹 foo2。

文件夹 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

您的帮助将不胜感激!

4

4 回答 4

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,将每一行与正则表达式匹配,并将具有相同名称的文件写入 directory foo2。它不检查foo2目录是否存在。

于 2013-05-25T12:18:43.780 回答
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
于 2013-05-25T17:48:18.977 回答
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分别包含源文件和输出文件的目录。

于 2013-05-25T16:44:35.293 回答
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

解释:

  • 在BEGIN语句中设置读路径和写路径。
  • 对于foo.txt文件中具有文件名的行
  • 使用substr捕获名为file的变量中的文件名
  • 在名为var的变量中读取文件。
  • 拆分变量var以使用第 3 列和第 4 列作为数组ary的索引。
  • 如果数组中存在第一列作为索引,则从 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
于 2013-05-25T17:26:22.017 回答