【问题标题】:How to expand 2nd argument if it's a glob pattern?如果它是全局模式,如何扩展第二个参数?
【发布时间】:2015-06-11 07:41:11
【问题描述】:

我正在尝试编写一个脚本来计算文件列表中某些模式的匹配次数并输出其结果。本质上我想这样调用命令:

count-per-file.sh str_needle *.c

并获得如下输出:

Main.c: 12
Foo.c: 1

脚本:

#!/bin/bash
# Count occurences of pattern in files.
#
# Usage:
#   count-per-file.sh SEARCH_PATTERN GLOB_EXPR
for file in "$2"; do
    count=$(grep -a "$1" "$file" | wc -l)
    if [ $count -gt 0 ]; then
        echo "$file: $count"
    fi
done

问题是如果我这样称呼它,所以我不知道如何遍历文件列表,所以这不会输出任何内容:

count-per-file.sh str_needle *.c

我找到了this answer,但它处理 glob 模式是脚本的唯一参数,而在我的脚本中,第一个参数是搜索模式,其余的是从 glob 扩展的文件。

【问题讨论】:

  • 如果你把它称为count-per-file.sh str_needle *.c,那么第二个参数就不是*.c;您的 shell 会将其扩展为 Main.cFoo.c(作为第二个和 第三个 参数s)。
  • @Biffen 对,如果我的第一个参数始终是 search_pattern,我将如何遍历这些文件?
  • shift,然后是for file。你知道grep -oc str_needle *.c 做你想做的事,对吧? grep ...|wc -l 不会给你出现的次数,而只是行数?
  • shift 然后for file in "$@"
  • 我会继续阅读shift 谢谢。 grep 命令类似,但它列出了所有文件,即使没有匹配项,而我的脚本仅列出至少有一个匹配项的文件。

标签: bash glob


【解决方案1】:

正如建议的那样,我使用了shift,这似乎“弹出”了第一个参数。这是我的工作脚本:

#!/bin/bash
# Count occurences of pattern in files.
#
# Usage:
#   count-per-file.sh SEARCH_PATTERN GLOB_EXPR
search_pattern="$1"
shift

for file in "$@"; do
    count=$(grep -aiE "$search_pattern" "$file" | wc -l)
    if [ $count -gt 0 ]; then
        echo "$file: $count"
    fi
done

【讨论】:

  • shift 不弹出;它改变了。弹出是删除列表的最后一个
  • 他在非正式地使用“pop”。
【解决方案2】:

我想这就是你想要的

#!/bin/bash
# Count occurences of pattern in files.
#
# Usage:
#   count-per-file.sh SEARCH_PATTERN GLOB_EXPR
for file in $2; do                               #UNQUOTE THIS TO EXPAND GLOB
    count=$(grep -a "$1" "$file" | wc -l)
    if [ $count -gt 0 ]; then
        echo "$file: $count"
    fi
done

然后将 glob 用引号括起来,这样它就不会在命令行上展开

count-per-file.sh str_needle '*.c'

【讨论】:

  • 这行不通,因为它只执行循环的一次迭代,其中$file 是全局扩展中的第一个文件。
  • 哦,它确实有效,我必须在引号中传递 glob 参数,谢谢
【解决方案3】:

您可以在传递*.c 时添加引号,并在for 循环中使用它们时删除引号,它会起作用..

[root@client1 ~]# cat  count-per-file.sh
#!/bin/bash
# Count occurences of pattern in files.
#
# Usage:
#   count-per-file.sh SEARCH_PATTERN GLOB_EXPR
for file in $2; do
    count=$(grep -a "$1" $file | wc -l)
    if [ $count -gt 0 ]; then
        echo "$file: $count"
    fi
done
[root@client1 ~]# bash count-per-file.sh str_needle "*.c"
file.c: 1
Main.c: 12
[root@client1 ~]#

【讨论】:

    【解决方案4】:

    您可以使用带有像这样的起始索引的子字符串参数扩展来跳过$@中的前n-1个值

    "${@:n}"

    例如

    for FILE in "${@:2}" 
    do
      echo $FILE
    done
    

    注意您的脚本没有将“glob 模式”作为第二个参数。 调用您的脚本的 shell 将 glob 扩展为以空格分隔的文件列表在您的脚本看到它之前,并将其作为参数列表传递给您的脚本。这就是为什么你可以使用standard substring range expansion

    【讨论】:

      猜你喜欢
      • 2013-03-18
      • 2020-06-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-15
      • 1970-01-01
      • 2017-12-03
      相关资源
      最近更新 更多