[英]bash and grep: passing of regex parameter
I'm trying to write a bash script that helps solving crosswords. 我正在尝试编写一个bash脚本来帮助解决填字游戏。 For example, the question is "Alcoholic Drink in German".
例如,问题是“德语中的酒精饮料”。 I already have a 'B' at the first place, an 'R' at the last place and two gaps in between.
我已经在第一位置有一个“ B”,在最后位置有一个“ R”,并且两者之间有两个间隙。 So a regex would be $B..R^ Since I live in Switzerland, I'd like to use the ngerman dictionary (DICT=/usr/share/dict/ngerman).
正则表达式为$ B..R ^因为我住在瑞士,所以我想使用ngerman词典(DICT = / usr / share / dict / ngerman)。 Here's how I'd do it directly on the shell:
这是我直接在shell上执行的方法:
grep -i '^B...$' /usr/share/dict/ngerman
That works perfectly, and the word 'Bier' appears among three others. 效果非常好,“ Bier”一词出现在其他三个词中。 Since this syntax is cumbersome, I'd like to write a little batch script, that allows me to enter it like this:
由于此语法很麻烦,因此我想编写一个批处理脚本,该脚本允许我这样输入:
crosswords 'B..R'
Here's my approach: 这是我的方法:
#!/bin/bash
DICT=/usr/share/dict/ngerman
usage () {
progname=$(basename $0)
echo "usage: $progname regex"
}
if [ $# -le 0 ]; then
usage
exit 1
fi
regex="'^$1$'"
cmd="grep -i $regex $DICT"
echo $regex
echo $cmd
$($cmd) | while read word; do
echo "$word"
done
But nothing appears, it doesn't work. 但是什么也没出现,这是行不通的。 I also output the
$regex
and the $cmd
variable for debugging reasons. 出于调试原因,我还输出了
$regex
和$cmd
变量。 Here's what comes out: 结果如下:
'^B..R$' '^ $ B..R'
grep -i '^B..R$' /usr/share/dict/ngerman
That's exactly what I need. 那正是我所需要的。 If I copy/paste the command above, it works perfectly.
如果我复制/粘贴上面的命令,它会完美运行。 But if i call it with
$($cmd)
, it fails. 但是,如果我用
$($cmd)
调用它,它将失败。 What is wrong? 怎么了?
Change regex="^'$1$'"
to regex="^$1$"
and $($cmd)
to $cmd
将
regex="^'$1$'"
更改为regex="^$1$"
,将$($cmd)
更改$cmd
Here is a fixed version: 这是固定版本:
#!/bin/bash
DICT=/usr/share/dict/ngerman
usage () {
progname=$(basename "$0")
echo "usage: $progname regex"
}
if [ $# -le 0 ]; then
usage
exit 1
fi
regex="^$1$"
cmd="grep -i $regex $DICT"
echo "$regex"
echo "$cmd"
$cmd | while read -r word; do
echo "$word"
done
But this script has potential problems. 但是此脚本有潜在的问题。 For example try running it as
./script 'asdads * '
. 例如,尝试将其作为
./script 'asdads * '
。 This will expand to all files in a directory and all of them are going to be passed to grep. 这将扩展到目录中的所有文件,并且所有文件都将传递给grep。
Here is a bit improved version of your code with correct quoting and also with bonus input validation: 这是您的代码经过改进的版本,带有正确的引号和附加的输入验证:
#!/bin/bash
DICT=/usr/share/dict/ngerman
usage () {
progname=$(basename "$0")
echo "usage: $progname regex"
}
if [ $# -le 0 ]; then
usage
exit 1
fi
if ! [[ $1 =~ ^[a-zA-Z\.]+$ ]]; then
echo 'Wrong word. Please use only a-zA-Z characters and dots for unknown letters'
exit 1
fi
grep -i "^$1$" "$DICT" | while read -r word; do
echo "$word"
done
you do not need to put quotes around regex variable string. 您不需要在正则表达式变量字符串前后加上引号。 and
$($cmd)
should change to $cmd
并且
$($cmd)
应该更改为$cmd
so the correct code is : 所以正确的代码是:
#!/bin/bash
DICT=/usr/share/dict/ngerman
usage () {
progname=$(basename $0)
echo "usage: $progname regex"
}
if [ $# -le 0 ]; then
usage
exit 1
fi
regex="^$1$"
cmd="grep -i $regex $DICT"
echo $regex
echo $cmd
$cmd | while read word; do
echo "$word"
done
Oh, now I got it. 哦,现在我明白了。 When I do it manually, '' are expanded!
当我手动执行时,''将展开! Here's my test program in C (param-test.c):
这是我在C中的测试程序(param-test.c):
#include <stdio.h>
int main(int argc, char *argv[]) {
puts(argv[1]);
return 0;
}
Then I call: 然后我打电话给:
param-test 'foo'
And I see: 我看到:
foo
That's the problem! 那就是问题所在! grep doesn't really get 'B..R', but just B..R.
grep并没有真正得到“ B..R”,而只是得到了B..R。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.