spo*_*ovy 5 bash shell printf string-formatting
对我来说一个持续的烦恼(次要,但不变)是我不能(或不知道如何)在 bash 代码中将字符串拆分为多行。我有的是这个:
while getopts 'd:h' argv; do
case "${argv}" in
d) local target_dir="${OPTARG}" ;;
h)
printf "Usage: remove_file_end_strings [ -d <work directory> ] <string to remove>\n"
return 1
;;
esac
Run Code Online (Sandbox Code Playgroud)
这里看起来不错,因为没有自动换行,但是当限制为 80 个字符并且自动换行时看起来很不整洁。当我想要的是这样的东西时,这在 python 或 ruby 中很简单:
while getopts 'd:h' argv; do
case "${argv}" in
d) local target_dir="${OPTARG}" ;;
h)
printf "Usage: remove_file_end_strings [ -d <work "
"directory> ] <string to remove>\n"
return 1
;;
esac
Run Code Online (Sandbox Code Playgroud)
我的 google-fu 让我失望了,所以有没有办法在 bash 中实现这一点,还是我只需要继续用力咬一块木头?塔
编辑:我刚刚决定了我的次优解决方案:
while getopts 'd:h' argv; do
case "${argv}" in
d) local target_dir="${OPTARG}" ;;
h)
printf "Usage: remove_file_end_strings [ -d <work "
printf "directory> ] <string to remove>\n"
return 1
;;
esac
done
Run Code Online (Sandbox Code Playgroud)
断行很容易,但在缩进下一行时更难不引入任何额外的空格或标记边界。没有缩进,它很简单但很丑陋:
{
printf "Usage: remove_file_end_strings \
[ -d <work directory> ] <string to remove>\n"
}
Run Code Online (Sandbox Code Playgroud)
无论好坏,echo它接受的东西都比较草率:
echo 'This is my string' \
'that is broken over' \
'multiple lines.'
Run Code Online (Sandbox Code Playgroud)
这将 3 个参数传递给 echo 而不是 1,但由于参数用空格连接,因此效果相同。
在您的情况下,当您将整个消息放入格式字符串时,您可以模拟相同的行为:
printf "%b " 'This is my string' \
'that again is broken' \
'over multiple lines.\n'
Run Code Online (Sandbox Code Playgroud)
虽然很明显,当你有一个带有不同插槽的正确格式字符串时,这并不能很好地工作。
在这种情况下,有黑客:
printf "I am also split `
`across %s `
`lines\\n" \
"a number of"
Run Code Online (Sandbox Code Playgroud)
将内联文档与<<-运算符一起使用:
while getopts 'd:h' argv; do
case "${argv}" in
d) local target_dir="${OPTARG}" ;;
h)
cat <<-EOT
Usage: remove_file_end_strings [ -d <work directory> ] <string to remove>
EOT
esac
done
Run Code Online (Sandbox Code Playgroud)
查看man bash并寻找Here Documents:
如果重定向运算符为 <<-,则所有前导制表符将从输入行和包含定界符的行中去除。这允许 shell 脚本中的此处文档以自然的方式缩进。
如果需要在行中换行,请通过管道传输一个sed命令,该命令将删除字符串之间的制表符:
while getopts 'd:h' argv; do
case "${argv}" in
d) local target_dir="${OPTARG}" ;;
h)
cat <<-EOT | sed 's/\t*\([^\t]*\)/ \1/2g'
Usage: remove_file_end_strings [ -d <work \
directory> ] <string to remove>
EOT
esac
done
Run Code Online (Sandbox Code Playgroud)