在匹配给定值的文件中查找正则expression式

我有一些使用正则expression式与grep(bash)的基本知识。 但是我想用另一种方式来使用正则expression式。

例如,我有一个文件,其中包含以下条目:

line_one=[0-3] line_two=[4-6] line_three=[7-9] 

现在我想使用bash来找出一个特定的数字匹配的行。 例如:

 grep 8 file 

应该返回:

 line_three=[7-9] 

注:我知道“grep 8文件”的例子没有意义,但我希望它有助于理解我想要实现的。

谢谢你的帮助,Marcel

正如其他人所指出的, awk是正确的工具:

awk -F'=' '8~$2{print $0;}' file

…如果你想让这个工具更像grep,一个快速的bash包装:

 #!/bin/bash awk -F'=' -v seek_value="$1" 'seek_value~$2{print $0;}' "$2" 

这将运行像:

 ./not_exactly_grep.sh 8 file line_three=[7-9] 

这可以在本地bash中使用语法[[ $value =~ $regex ]]来测试:

 find_regex_matching() { local value=$1 while IFS= read -r line; do # read from input line-by-line [[ $line = *=* ]] || continue # skip lines not containing an = regex=${line#*=} # prune everything before the = for the regex if [[ $value =~ $regex ]]; then # test whether we match... printf '%s\n' "$line" # ...and print if we do. fi done } 

用作:

 find_regex_matching 8 <file 

…或者用你的示例输入内联来测试它:

 find_regex_matching 8 <<'EOF' line_one=[0-3] line_two=[4-6] line_three=[7-9] EOF 

…正确发射:

 line_three=[7-9] 

您可以用printf '%s\n' "${line%%=*}"来代替printf '%s\n' "$line" ,只打印密钥( =之前的内容)。 请参阅参数扩展的bash-hackers页面,了解涉及的语法。

我的第一印象是,这不是一个grep的任务,也许是awk。

试图用grep做事情我只看到这个:

 for line in $(cat file); do echo 8 | grep "${line#*=}" && echo "${line%=*}" ; done 

使用while进行文件阅读(以下注释):

 while IFS= read -r line; do echo 8 | grep "${line#*=}" && echo "${line%=*}" ; done < file 

这不是grep内置功能,但是使用awk很容易,只需要更改语法:

 /[0-3]/ { print "line one" } /[4-6]/ { print "line two" } /[7-9]/ { print "line three" } 

如果你真的需要的话,你可以编程方式将你的输入文件改成这个语法,如果它不包含任何需要转义的字符(主要是/在正则表达式或"在字符串中”):

 sed -e 's@\(.*\)=\(.*\)@/\2/ { print "\1" }@' 

据我所知,你正在寻找一个包括一些价值的范围。

你可以在gawk做到这一点:

 $ cat /tmp/file line_one=[0-3] line_two=[4-6] line_three=[7-9] $ awk -vn=8 'match($0, /([0-9]+)-([0-9]+)/, a){ if (a[1]<n && a[2]>n) print $0 }' /tmp/file line_three=[7-9] 

由于数字被视为数字(与正则表达式),它支持更大的范围:

 $ cat /tmp/file line_one=[0-3] line_two=[4-6] line_three=[75-95] line_four=[55-105] $ awk -vn=92 'match($0, /([0-9]+)-([0-9]+)/, a){ if (a[1]<n && a[2]>n) print $0 }' /tmp/file line_three=[75-95] line_four=[55-105] 

如果你只是想将=的右边解释为正则表达式,你可以这样做:

 $ awk -F= -v tgt=8 'tgt~$2' /tmp/file 

你想要做类似的事情

 grep -Ef <(cut -d= -f2 file) <(echo 8) 

这将grep grep你想要什么,但不会显示在哪里。 用grep你可以显示一些消息:

 echo "8" | sed -n '/[7-9]/ s/.*/Found it in line_three/p' 

现在你想将你的正则表达式文件转换成这样的命令:

 sed 's#\(.*\)=\(.*\)#/\2/ s/.*/Found at \1/p#' file 

将这些命令存储在虚拟命令文件中,您将拥有这些命令

 echo "8" | sed -nf <(sed 's#\(.*\)=\(.*\)#/\2/ s/.*/Found at \1/p#' file)