我有一些使用正则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)