bash 脚本中的 printf 空白字符

bash 脚本中的 printf 空白字符

为了当前在 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映射somekeysomevalue,则设置变量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

相关内容