我的任务是:输入六个字符串和一个文件名,从这六个字符串中拉出至少满足三个模式的所有行。
例如:./test.sh p1 p2 p3 p4 p5 p6 file.txt
,因此行aabbbp1p3p5p4
匹配,但oop4op2ooo
不匹配。
那么在命令行中几行写命令sed
或grep
的重点是什么? (awk
也可以尝试,但是我对此不太熟悉)
我最后要做的就是征求排列。
答案 0 :(得分:0)
这就是我要怎么做。我更改了参数的顺序,因此第一个参数是文件名,所有其他参数都是模式:
#!/bin/bash
[[ "$#" -lt 4 ]] && { echo "You need at least 4 arguments. A filename and 3 patterns"; exit 3;}
filename="$1" && shift
patterns=( $@ )
[[ ! -f "$filename" ]] && { echo "File '$filename' does not exist"; exit 4;}
matches=0
while read line
do
matches=0
for p in "${patterns[@]}"
do
grep -q "$p" <( echo "$line" ) && (( matches++ ))
done
[[ "$matches" -ge 3 ]] && echo "$line";
done <<< "$( cat $filename )"
exit 0
希望有帮助!
答案 1 :(得分:0)
理想情况下,您需要可扩展的高效解决方案。对于脚本编写,这意味着要运行尽可能少的外部命令(每个外部命令(如grep
都需要大量资源来启动)。
以下解决方案将仅读取数据文件6次(每次都是一个grep),计算每行的匹配数,并仅打印> = 3个匹配项的行。
patterns=("$1" "$2" "$3" "$4" "$5" "$6")
file=$7
for p in "${patterns[@]}" ; do grep -- "$p" "$file" ; done |
sort |
uniq -c |
awk '$1 >= 3 { print gensub("^ *[0-9]+ ", "", 1) }'
答案 2 :(得分:0)
无需使用其他工具。
全部重击-
pats=("$1" "$2" "$3" "$4" "$5" "$6") # get the patterns
file="$7" # assign the source
while read -r line # read each line
do declare -i hits=0 # initialize hits
for p in "${pats[@]}" # loop through patterns
do case "$line" in # comparing to input
*"$p"*) (( hits++ )) ;; # increment on match
esac
done
(( hits > 2 )) && echo "$line" # print on threshhold
done < "$file" # reading from file
p1 p2 p3 p4 p5 p6
p1 p2 p3 p4 p5
p1 p2 p3 p4
p1 p2 p3
p1 p2
p1
.
已执行:
$: ./test.sh p1 p2 p3 p4 p5 p6 file.txt
p1 p2 p3 p4 p5 p6
p1 p2 p3 p4 p5
p1 p2 p3 p4
p1 p2 p3
答案 3 :(得分:0)
这可能对您有用(GNU并行):
parallel '(({1}<{2})) && (({2}<{3})) && echo "/p{1}/{/p{2}/{/p{3}/b}}"' ::: {1..6} ::: {2..6} ::: {3..6} |
sed -f - -e 'd' filename.txt
这将过滤掉filename.txt
中来自集合{p1,p2,p3,p4,p5,p6}
中3个或更多匹配项的所有行。