[英]Extracting lines from text files in a folder based on the numbers in another file
我有一個文件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
你的幫助將不勝感激!
更新
這是一個純粹的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
目錄是否存在。
這可能適合你(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
到包含源文件和輸出文件的目錄中。
你可以試試這樣的東西 -
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
#!/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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.