![bash 脚本中的 printf 空白字符](https://linux22.com/image/19070/bash%20%E8%84%9A%E6%9C%AC%E4%B8%AD%E7%9A%84%20printf%20%E7%A9%BA%E7%99%BD%E5%AD%97%E7%AC%A6.png)
为了当前在 Cygwin 客户端中运行的脚本的目的,如何在 printf 中转义空白字符?包含空格的行(它本身在命令行中工作为回显$SPC) 是
SPC=$(printf \\$(printf '%03o' 32))
如果您可能想知道为什么,在这段代码中,我试图模拟一个关联数组,使其不依赖于 Bash 4+...希望这是一个理论上可以在几乎任何 bash 环境中运行的通用示例。
这是整个脚本:
#!/bin/bash
DEFAULT_INDEX=""
LAST_INDEX=0
SPC=$(printf \\$(printf '%03o' 32))
# MICROSOFT OUTLOOK VERSIONS.
OUTLOOKS=( "Cancel^Do$SPCnot$SPCtry$SPCto$SPCsend$SPCmessage$SPCvia$SPCOutlook"
"URL^Just$SPCthe$SPCmailto$SPCURL"
"Outlook$SPC2003^C:\Program$SPCFiles\Microsoft$SPCOffice\Office12"
"Outlook$SPC2007^C:\Program$SPCFiles\Microsoft$SPCOffice\Office12"
"Outlook$SPC2010^C:\Program$SPCFiles\Microsoft$SPCOffice\Office14" )
# ITERATES THROUGH ARRAY AND MAKES NUMBERED SELECTION LIST.
printOutlooksArraySelectionList() {
LIST_TITLE="MICROSOFT OUTLOOK SELECTION LIST"
echo
printf "\t\t\E[37;1;44m%-0s %s %s %s\033[0m" $LIST_TITLE
echo
echo
DEFAULT_VALUE="Outlook 2010"
index=0
for i in "${OUTLOOKS[@]}"; do
key=${i%%^*}
value=${i##*^}
if [ "$key" == "$DEFAULT_KEY" ]; then
DEFAULT_INDEX=$index
fi
printf "\t\E[37;44m%-3s %-13s\033[0m \E[1;34;40m%-41s\033[0m\n" \
$index $key $value
echo
((index++))
done
# SETS LAST_INDEX TO INDEX VALUE OF LAST ITEM IN ARRAY.
((LAST_INDEX = index - 1))
}
printOutlooksArraySelectionList
希望输出如下所示:
MICROSOFT OUTLOOK SELECTION LIST
0 Cancel Do not try to send message via Outlook
1 URL Just the mailto URL
2 Outlook 2003 C:\Program Files\Microsoft Office\Office12
3 Outlook 2007 C:\Program Files\Microsoft Office\Office12
4 Outlook 2010 C:\Program Files\Microsoft Office\Office14
为了解决这个问题,我最终没有使用 printf,而是:
echo -e "\t\E[37;44m${index}\t${key}\033[0m\t\t\E[1;34;40m${value}\033[0m"
这个脚本足以满足我的目的。
答案1
我不明白你想做什么。您的代码确实设置SPC
为长度为 1 的字符串,其单个字符是空格。这是一种非常复杂的方法:SPC=" "
同样有效并且易于理解。
我还没有审阅你的整个脚本,但我后来确实发现了一些问题:你写了诸如"URL^Just$SPCthe$SPCmailto$SPCURL"
.这会生成字符串URL^Just
,因为变量$SPCthe
、$SPCmailto
和$SPCURL
尚未定义。当变量扩展后紧跟可能是变量名称一部分的字符时,您需要表示变量名的结尾,例如将名称放入大括号中:URL^Just${SPC}the${SPC}mailto${SPC}URL
。不过我不明白你为什么不写信"URL^Just the mailto URL"
。
对于小型哈希表的编码,我建议使用两个数组,一个用于键,一个用于值。这样,您可以存储任意字符串,而不必担心编码问题。下面是查找和加法的草图(将keys
和数组的名称values
作为参数留作练习):
lookup () { # $1=key; set value to the value found
for ((i=1; i<=${#keys}; i++)); do
if [[ ${keys[$i]} = $1 ]]; then value=${values[$i]}; return 0; fi
done
unset value; return 1
}
add () { # $1=key $2=value
for ((i=1; i<=${#keys}; i++)); do
if [[ ${keys[$i]} = $1 ]]; then values[$i]=$2; return; fi
done
keys[$i]=$1; values[$i]=$2
}
更有效的方法是将每个条目存储在 shell 变量中。例如,如果表foo
映射somekey
到somevalue
,则设置变量table_foo_somekey=somevalue
。您需要将密钥编码为字母数字,这并不简单(一种方法是对密钥进行哈希处理,例如使用 sha1,并将密钥存储在 中,table_foo_${sha1_of_somekey}_key
将值存储在 中table_foo_${sha1_of_somekey}_key
)。如果需要枚举表中的键,则需要单独存储列表。
或者,当您需要的东西超出了简单 shell 的功能时,您可以使用更强大的工具。 Ksh93(不是 pdksh)、bash 4 和 zsh 都有关联数组。除此之外,还有 Perl 和 Python 以及其他语言。
答案2
由于您已经在字符串周围使用了引号,因此
$SPC
不需要在字符串中使用引号,并且可以为您提供没有好处。你不需要任何的定义空间那里。作为吉尔斯指出,字符串
like "URL^Just$SPCthe$SPCmailto$SPCURL"
包含不存在的变量。变量以不能在任何变量名中使用的字符结尾,或者用{}
as 中的(正确)分隔时结束${key}
。
答案3
我已经提到过对这个问题的一些误解。但不管怎么说。
包含空格的行(它本身在命令行中作为 echo $SPC 工作)是
SPC=$(printf \\$(printf '%03o' 32))
实际上,该行不包含任何空格。它扩展于
printf \\040
它的扩张没有什么好处。 ingprintf
输出printf
根本不是一个好主意。
如果需要,Print 可以显示空格符号:
$> printf ' %03o\n' 32
040
前导空值和前导零:
$> printf "%010o\n" 32
0000000040
$> printf "% 10o\n" 32
40
UPD通过评论:
$> printf '\\%03o\n' 32
\040