如何从shell使用fnmatch?

时间:2014-12-29 05:04:02

标签: shell glob

在通用shell脚本中,我想使用shell模式匹配来过滤文本文件的行。

我在files.txt中有一个文件名列表:

file1.txt
file2.sh
file3.png

我在patterns.txt中有一个模式列表:

other_file.txt
file2.*

如果我在patterns.txt中有正则表达式,我可以这样做:

$ grep -v -f patterns.txt files.txt

但我想使用shell globbing模式。我找到了C函数fnmatch但没有使用shell / unix命令。

1 个答案:

答案 0 :(得分:0)

好的,这将是非常不合格的,因为POSIX sh甚至没有数组(我会用它来缓存模式):

while IFS= read -r filename; do
    hasmatch=0
    while IFS= read -r pattern; do
        case $filename in ($pattern) hasmatch=1; break ;; esac
    done <patterns.txt
    test $hasmatch = 1 || printf '%s\n' "$filename"
done <files.txt

如果您不需要位置参数($1$2,...),您可以滥用这些参数进行模式缓存:

saveIFS=$IFS; IFS='
'; set -o noglob
set -- $(cat patterns.txt)
IFS=$saveIFS; set +o noglob
while IFS= read -r filename; do
    hasmatch=0
    for pattern in "$@"; do
        case $filename in ($pattern) hasmatch=1; break ;; esac
    done
    test $hasmatch = 1 || printf '%s\n' "$filename"
done <files.txt

请注意那里的空白:我们将IFS设置为文字换行符而不是其他内容,即IFS=' 输入 '

我已经使用您的数据集加上一些附加内容(例如a b*模式来测试空白行为)来测试它,并且根据OP中的规范它似乎对我有效。