如何使用 IFS 将字符串拆分为字母并在无空格/空、空格和字符 - 处读取?

如何使用 IFS 将字符串拆分为字母并在无空格/空、空格和字符 - 处读取?

我有一根绳子-w o rd
我需要将其拆分为w o r d数组或数组,因为'w' 'o' 'r' 'd' 这并不重要。
我尝试过以下方法

IFS='\0- ' read -a string <<< "-w o rd"  
echo ${string[*]}

rd没有被分裂。我怎样才能让它分开

答案1

你不能在 bash 中使用 IFS 来分割任何东西(它成为一个角色)。rd 之间没有字符rd。没有空格和没有字符与空字符不同。

如果您希望每个字符作为数组中的单独元素,我能想到的一种方法是单独读取每个字符并将其附加到数组中(并使用 IFS 去除空格和-):

bash-4.4$ while IFS=' -' read -n1 c ; do [[ -n $c ]] && foo+=("$c"); done <<<"-w o rd"
bash-4.4$ declare -p foo
declare -a foo=([0]="w" [1]="o" [2]="r" [3]="d")

答案2

您可以使用以下方法删除不需要的字符${var//pattern/replacement}

s='-w o rd'
s=${s//[- ]}

然后使用子字符串扩展一次选择一个字符:

$ for ((i=0; i < ${#s}; i++)); do
      echo ${s:i:1};           # or do whatever you like here
  done

(它甚至似乎可以处理多字节字符,至少在我的系统上是这样。)


请注意,IFS='\0- '将分配一个文字反斜杠,IFS因为反斜杠在单引号内没有特殊含义。八进制转义可以在 中工作$'...',但 Bash 中的变量不能包含 NUL 字节,所以这没有帮助。 (字符串在 NUL 上被剪切,因此例如x=$'foo\0bar'; printf "%q\n" "$x"仅打印foo。另外,@muru 所说的,在 NUL 字节上拆分与在每个字符之间拆分不同)

答案3

如果你的字符串不太长:

w='-w o rd baa'
w=${w//[!a-z]}  # strip anything but lower case letters
eval echo '${w:'{0..10}':1}'
eval array=\( '${w:'{0..10}':1}' \)
echo "${array[@]}"

w o r d b a a

您可以将愚蠢的事情变成更糟糕的事情,IFS 和 glob 安全,并且考虑到大括号的相对顺序以及 ,zshbash之间的变量扩展ksh

args(){ printf '<%s> ' "$@"; echo; }
w='-e a * () \n peek
    fo*"x'"'q"
eval eval args "'\"\${w:'{0..$((${#w}-1))}':1}\"'"
eval eval 'array=\(' "'\"\${w:'{0..$((${#w}-1))}':1}\"'" '\)'
args "${array[@]}"

<-> <e> < > <a> < > <*> < > <(> <)> < > <\> <n> < > <p> <e> <e> <k> <
> <     > <f> <o> <*> <"> <x> <'> <q>    

但坦率地说,这种怪物的唯一用途可能是吓跑新手,并通过假设对 shell 语言细节的深入了解来给傻瓜留下深刻印象;-)

相关内容