【问题标题】:How to prevent glob patterns from expanding while splitting colon separated glob patterns by colon?如何在用冒号分割冒号分隔的 glob 模式时防止 glob 模式扩展?
【发布时间】:2015-08-18 03:37:55
【问题描述】:

这是我为 POSIX shell 编写的 shell 脚本。我的目标是 POSIX shell 兼容性。有一个 PATTERNS 变量包含冒号分隔的全局模式。此变量是用户输入。我无法改变这一点。其余代码是我的代码,我可以更改它以实现我的目的。下面的小演示程序的目的是将每个 glob 模式记录(或显示)在单独的行上。

PATTERNS=*.*:*.txt:*.html
IFS=:
for pattern in $PATTERNS
do
    unset IFS
    echo Pattern: "$pattern"
done

这是当前工作目录。

$ ls
a.txt  b.txt  foo.sh

当我运行代码时,我得到了这个输出。

$ sh foo.sh 
Pattern: a.txt
Pattern: b.txt
Pattern: foo.sh
Pattern: a.txt
Pattern: b.txt
Pattern: *.html

它不是在一行中显示每个 glob 模式,而是在一行中显示与 glob 模式匹配的每个文件。由于*.html 与当前目录中的任何文件都不匹配,因此只根据需要显示了这个 glob 模式。

我想要的输出是:

Pattern: *.*
Pattern: *.txt
Pattern: *.html

所以我希望不将 glob 模式扩展到当前目录中的文件名中。我怎样才能做到这一点?该解决方案必须适用于任何 POSIX shell。

【问题讨论】:

    标签: shell posix glob


    【解决方案1】:

    不是肯定的,我没有错过任何东西,或者没有更好的方法,但这不是使用任何我知道是不可移植的东西。

    #!/bin/sh
    
    PAT="*.rc:*.rpms:*.sh"
    
    # Function so we can repeatedly expand the remaining string.
    read_next() {
        IFS=: read hd tl <<EOF
    $1
    EOF
    }
    
    tl=$PAT
    while read_next "$tl" && [ -n "$hd" ]; do
        echo "Pattern: $hd"
    done
    

    或者,这更简单,尽管它需要“全局”IFS 修改,我从来都不喜欢(我非常喜欢 read 上的范围 IFS 修改)以及修改全局 shell 设置您可以简单地使用 -f 标志完全禁用路径名扩展至 set(然后如果需要,然后使用 set +f 重新启用它),然后只保留原始循环。

    【讨论】:

    • 感谢您提供代码示例的详细回复。您是否考虑过使用set +f 禁用全局扩展?你觉得使用这个有什么问题吗?它似乎在 POSIX 中定义为 pubs.opengroup.org/onlinepubs/9699919799/utilities/…
    • 我做到了。我的意思是检查然后提到实际上但显然忘记这样做了。
    猜你喜欢
    • 1970-01-01
    • 2021-03-12
    • 2015-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多