简体   繁体   English

bash和grep:传递正则表达式参数

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM