bash - 如何在 bash 中连接使用 printf 格式化的字符串

标签 bash shell printf

我需要在循环中连接几个字符串并将结果分配给变量:

格式化字符串示例:

result=$(printf '| %-15s| %-25s| %-15s| %-15s| %-15s\n' $size $name $visits $inbound $outbound);

在我看来它应该是这样工作的:

result=''
while read somevar
do
    ...
    outbound=`cat "$www_path/$name/access.log"|grep \`date +"%d/%b/%Y"\`|awk '{ sum+=$11} END {print sum/1024/1024}'`
    result=$(printf '%s| %-15s| %-25s| %-15s| %-15s| %-15s\n' $result $size $name $visits $inbound $outbound);
    ...
done
echo $result

但事实并非如此:(

更新:

完整代码如下:

www_path='/var/www';
result='';
cd /var/www/; ls -d */ | while read i ; do basename "$i" ; done
while read i;
do du -sh "$i"|
        while read size name
        do
                visits=`cat "$www_path/$name/access.log"|grep \`date +"%d/%b/%Y"\`|grep -v "internal dummy connection"|awk -F ' ' '{print $1}'  | sort | uniq | wc -l|tr '\n' '\t'|sed 's/$/\t/'`
                inbound=`cat "$www_path/$name/access.log"|grep \`date +"%d/%b/%Y"\`|grep -v "internal dummy connection"|awk '{ sum+=$10} END {print sum/1024/1024}'|tr '\n' '\t'|sed  's/$/\t\t/'`
                outbound=`cat "$www_path/$name/access.log"|grep \`date +"%d/%b/%Y"\`|grep -v "internal dummy connection"|awk '{ sum+=$11} END {print sum/1024/1024}'`;
                result=$(printf '%s| %-15s| %-25s| %-15s| %-15s| %-15s\n' "$result" "$size" "$name" "$visits" "$inbound" "$outbound")
        done
done
echo $result

最佳答案

如果要将 $result 和所有其他可能包含空格和其他特殊字符的变量用作程序或内置函数的单个参数,请使用双引号:

result=$(printf '%s| %-15s| %-25s| %-15s| %-15s| %-15s\n' "$result" "$size" "$name" "$visits" "$inbound" "$outbound")

如果你只是想将 printf 的结果赋给一个变量(就像你所做的那样),你也可以使用

printf -v result '%s| %-15s| %-25s| %-15s| %-15s| %-15s\n' "$result" "$size" "$name" "$visits" "$inbound" "$outbound"

顺便说一句:还有一个 += 赋值运算符,它只是附加到字符串(参见 bash 手册页,参数部分)。

在完整的代码 list 中,在第二个“while read i”之前的“done”之后缺少管道符号。

当你打电话的时候

echo $result

$result 的内容已经丢失,因为在“do du ...”之后的管道符号创建的子进程中调用了 printf。父进程无法访问子进程的(环境)变量。

我宁愿将代码重写成类似的东西

result=""
for name in /var/www/* ; do 
    read size __ < <(du -sh "$name")
    name=${name##*/}
    #insert the other stuff here and add arguments to printf
    printf -v line '| %-15s| %-25s\n' "$size" "$name"
    result+=$line
done
echo "$result"

read < <(cmd)表达式类似于 cmd | read但是前者将命令放在子进程中,而读取则在主进程中执行。这样,通过 read 设置的变量也可以在后续命令中使用。

关于bash - 如何在 bash 中连接使用 printf 格式化的字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15992897/

相关文章:

linux - 如何使用文件内容作为命令行参数?

bash - 如果另一列的条件为 true,如何在 bash shell 中将一列划分为数字?

linux - Bash 并行执行和退出代码

bash - 如何从 cron 运行的脚本运行 gpg?

python - 使用 python 从重定向的标准输入读取输入

bash - 在数组中使用 grep

python - 可以混合使用 shell 和 python 脚本吗?

c - 将相同的浮点值相除,结果为0

java - Java中printf期间分离列表元素

c++ - 打印出字符串指针中获取的数据时出错