Bash 在计算字符串中的字符时,如何修复回音

Bash 在计算字符串中的字符时,如何修复回音,bash,Bash,我对for循环中的echo有一个问题,因为我想计算字符串字符,特别是“*”它,但它会打印当前目录中的所有文件 clearvar() { int=0 str=0 uniqchar=0 } countstring(){ for c in $(echo "${1}" | fold -w1); do echo "$c" if [[ $c == [0-9] ]];then int=$(( $

我对for循环中的echo有一个问题,因为我想计算字符串字符,特别是“*”它,但它会打印当前目录中的所有文件

clearvar() {
int=0
str=0
uniqchar=0
}

countstring(){
for c in $(echo "${1}" | fold -w1); do

                echo "$c"
                if [[ $c == [0-9] ]];then
                        int=$(( $int + 1 ))

                elif [[ $c == [a-Z] ]];then
                        str=$(( $str + 1 ))

                else
                        uniqchar=$(( $uniqchar + 1 ))
                fi
        done
}

while [ $# -gt 0 ];do

        echo "Argument input: $1"
        read -p "Input: " string
        rmws=$(echo $string | tr -d " ")

        mashed=$rmws$1
        countstring $mashed
        echo -e "int: $int\nstr: $str\nuniquechar: $uniqchar\nWhole string: $mashed"
        clearvar
        shift
done

示例输出:

Argument input: io1
Input: fj^*23                
f
j
^
file1
file2
file3
2
3
i
o
1
int: 3
str: 4
uniquechar: 4
Whole string: fj^*2wio1
它解释为echo*,而不是echo“*”。 所以我希望它不会打印出文件名

rmws=$(echo $string | tr -d " ")
如果
string=*
则只执行
echo*
并展开
*

同样的情况也发生在:

countstring $mashed
这两个扩展都是无引号的。用双引号把它们引起来。作为经验法则-始终使用双引号

同样的情况也发生在
for
循环中:

for c in $(echo "${1}" | fold -w1)
与其他地方一样,扩展是不带引号的,因此
*
扩展。你必须引用。这就是为什么$(..)中i的
被认为是不好的风格,因为这样的错误会发生。您不能对“$(…)”中的i执行
,因为这样您将迭代一个元素。要在流中的行或元素上迭代,请在IFS=read-r
循环时使用
。您可以使用ex.
sed's//&\n/g'
打印每一行上的每个字符,并在行上迭代,或者使用bash扩展名
read-n1
读取一个字符

while IFS= read -r -n1 c; do
   ..
done <<<"$1"
或者在bash中,您甚至可以执行以下操作:

(( int++ ))
# and so on
您的脚本可能会变成:

clearvar() {
    int=0
    str=0
    uniqchar=0
}

countstring(){
       while IFS= read -r -n1 c; do
                echo "$c"
                if [[ $c == [0-9] ]];then
                        (( int++ ))

                elif [[ $c == [a-Z] ]];then
                        (( str++ ))

                else
                        (( uniqchar++ ))
                fi
        done <<<"$1"
}

while [ $# -gt 0 ]; do
        echo "Argument input: $1"
        read -p "Input: " string
        rmws="$(echo "$string" | tr -d " ")"
        mashed="$rmws$1"
        countstring "$mashed"
        echo "int: $int"
        echo "str: $str"
        echo "uniquechar: $uniqchar"
        echo "Whole string: $mashed"
        clearvar
        shift
done

欢迎访问,请在您的问题中发布输入样本和预期样本输出,让我们在这里完成需求图片。我仍然不知道何时包装引号。谢谢,但它似乎仍然打印出目录文件,即使每个变量值都被引用。嗯。。。printf来自C语言-传递的参数被
%s
替换。因此,例如,
printf“%s”字符串“
只打印
字符串
。例如,
printf“在%s上的%s狐狸%s\n“棕色”跳过“狗”
将打印
棕色狐狸跳过狗
,然后换行。你可以在网上找到很多例子。谢谢,使用printf、tr和wc比使用循环计数字符更有意义。
clearvar() {
    int=0
    str=0
    uniqchar=0
}

countstring(){
       while IFS= read -r -n1 c; do
                echo "$c"
                if [[ $c == [0-9] ]];then
                        (( int++ ))

                elif [[ $c == [a-Z] ]];then
                        (( str++ ))

                else
                        (( uniqchar++ ))
                fi
        done <<<"$1"
}

while [ $# -gt 0 ]; do
        echo "Argument input: $1"
        read -p "Input: " string
        rmws="$(echo "$string" | tr -d " ")"
        mashed="$rmws$1"
        countstring "$mashed"
        echo "int: $int"
        echo "str: $str"
        echo "uniquechar: $uniqchar"
        echo "Whole string: $mashed"
        clearvar
        shift
done
countstring() {
       printf "%s" "$1" | tr -cd '[0-9]' | wc -c
       printf "%s" "$1" | tr -cd '[a-zA-Z]' | wc -c
       printf "%s" "$1" | tr -d '[0-9a-zA-Z]' | wc -c
}