实用方法

实用方法

我是 Bash 脚本的新手。

尝试编写一个简单的脚本,从标准输入(文件)读取并写入标准输出。我希望该脚本计算参数/算术扩展和命令替换的数量。

对于标准输入我到目前为止已经完成了以下操作:

file=${1--}
while IFS= read -r line; do 
  printf '%s\n' "$line"
done < <(cat - "$file")

答案1

实用方法

只需使用grep标志-c进行计数,或者更好的grep -o '<PATTERN>' | wc -l方法(请参阅后面的注释)。根据您希望输出的样子以及您想要实现的目标,有多种设置方法。

当然,参数扩展类型有很多种,所以我们需要为它们编写不同的模式。这里我只写了替换、前缀删除和算术扩展模式,但你可以将它们改编为任何其他模式。

在最基本的层面上,我们可以像这样调用单个命令:

$ cat ./myscript.sh                                                         
#!/bin/bash

var="string"
echo "${var/string/thread}"
echo $((2+2))
echo $((3*2))

echo ${var#*i}
echo ${var##*i}

echo ${var%i*}
echo ${var%%i*}
$ grep -c '${.*}' myscript.sh                                               
1
$ grep -c '$((.*))' myscript.sh                                             
2

这只是基本想法。您可以将多个grep模式放入一个脚本中,并带有良好的引导信息。例如:

#!/usr/bin/env bash
printf "\nNumber of arithmetic expansions:"
grep -c '$((.*))' "$1"
printf "\nNumber of substitutions:"
grep -c '${.*\/.*\/.*}' "$1"
printf "\nNumber of prefix removals:"
grep -c '${.*[#]\{1,2\}.*}' "$1"

然后像这样调用该脚本:

./count_bash_stuff.sh myscript.sh

或者,只需将所有模式放入文件中并调用grep即可-f。当然,它只会输出所有比赛的总数不是个别的:

$ cat ./patterns                                                            
$((.*))
${.*\/.*\/.*}
${.*[#]\{1,2\}.*}
$ grep -c -f ./patterns ./myscript.sh                                       
5

注意:正如steeldriver 在本答案下方的评论中指出的那样,grep是一个行匹配工具,这意味着如果一行中有多个模式,它将为该行添加 1 计数。更好的方法是使用-o标志grep并将输出传送到wc -l。因此,我们可以对算术扩展执行类似这样的操作:

grep -o '$((.*))' |  wc -l

POSIX shell 方式(不太实用)

是的,这是可能的。这很难,但使用case语句是可能的。这里我只会写出case算术扩展和最长前缀删除的语句。其余的就交给读者去适应和扩展吧。

再次提醒,请记住这只是概念验证。请注意,这使用的是/bin/sh- 在 Ubuntu 上,这是符合 POSIX 标准的/bin/dashshell,而不是bash

#!/usr/bin/env sh
while IFS="" read -r line || [ -n "$line" ];
do
    case "$line" in
        # arithmetic expansion, appearing anywhere in line
        *'$(('*'))'*) arithmetic_count=$(($arithmetic_count+1));;
        *'${'*##*'}'* ) prefix_count=$((prefix_count+1));;
    esac
done < "$1"

echo "$arithmetic_count"
echo "$prefix_count"

它的运行方式如下:

$ ./count_shell_stuff.sh myscript.sh                                                                                                                                   
2
1

你可能会问,为什么这不太实用?因为在 中编写模式case可能有些困难,而且比在grep或中编写模式要难一些Perl。另外,你必须case为每个 shell 语法结构编写模式。使用grep或 ,perl你可以将多个模式组合成一个。但话又说回来,这只是我个人的看法。正如我在这个小概念证明中所展示的那样,字符串模式匹配仍然非常有可能,但我不建议这样做。

相关内容