1

我正在尝试编写一个有助于解决填字游戏的 bash 脚本。例如,问题是“德语中的酒精饮料”。我已经有一个“B”在第一位,一个“R”在最后一个位置,中间有两个间隙。所以一个正则表达式是 $B..R^ 因为我住在瑞士,所以我想使用 ngerman 字典 (DICT=/usr/share/dict/ngerman)。以下是我直接在 shell 上执行此操作的方法:

    grep -i '^B...$' /usr/share/dict/ngerman

这非常有效,“Bier”这个词出现在其他三个词中。由于这种语法很麻烦,我想写一个小批处理脚本,这样我就可以像这样输入它:

    crosswords 'B..R'

这是我的方法:

#!/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

但是什么都没有出现,它不起作用。出于调试原因,我还输出了$regex和变量。$cmd这是结果:

'^B..R$'

grep -i '^B..R$' /usr/share/dict/ngerman

这正是我需要的。如果我复制/粘贴上面的命令,它会完美运行。但如果我用 调用它$($cmd),它会失败。怎么了?

4

3 回答 3

1

更改regex="^'$1$'"regex="^$1$"$($cmd)_$cmd

这是一个固定版本:

#!/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

但是这个脚本有潜在的问题。例如尝试将其运行为./script 'asdads * '. 这将扩展到目录中的所有文件,并且所有文件都将传递给 grep。

这是您的代码的一些改进版本,带有正确的引用以及额外的输入验证:

#!/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
于 2013-09-07T14:28:54.850 回答
1

您不需要在正则表达式变量字符串周围加上引号。并且$($cmd)应该更改为$cmd

所以正确的代码是:

#!/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
于 2013-09-07T14:31:33.997 回答
0

哦,现在我明白了。当我手动执行时, '' 被扩展!这是我用 C 语言编写的测试程序(param-test.c):

#include <stdio.h>
int main(int argc, char *argv[]) {
    puts(argv[1]);
    return 0;
}

然后我打电话:

    param-test 'foo'

我看到了:

    foo

那就是问题所在!grep 并没有真正得到 'B..R',而只是 B..R。

于 2013-09-07T14:56:54.710 回答