如何使用自定义分隔符拆分一行并分配给 BASH 中的变量?

how to split one line with customized separator and assign to variables in BASH?

首先我使用 IFS 阅读,但后来我发现 -- IFS 只能支持单个字符作为分隔符,有时我需要一个字符串作为分隔符。 然后,我在想也许使用 awk 和 eval 可以做到。所以我试试--

eisen@PVGN34701109A:/tmp> cat file1
hah   a#$hehe#$hoho
eisen@PVGN34701109A:/tmp> cat t2.sh
#!/bin/bash
eval $(awk -F'#\$' '{for (i=1;i<=NF;i++)   print "VAR"i"='\''"$i"'\''"}'  file1)
echo "VAR1=  ${VAR1}"
echo "VAR2=  ${VAR2}"
echo "VAR3=  ${VAR3}"
eisen@PVGN34701109A:/tmp> ./t2.sh
awk: warning: escape sequence `$' treated as plain `$'
VAR1=  hah a
VAR2=  hehe
VAR3=  hoho

起初,我觉得还好。但我立即发现了问题——在 file1 中,第一个值应该是“hah a”——里面有 3 个 space,但是在 awk 和 eval 之后——只剩下一个 space... 然后我分别用 awk 和 eval 进行了测试,我发现这是因为 eval 会“吃掉”一些 space--

eisen@PVGN34701109A:/tmp> eval "VAR1='hah   a'";echo $VAR1
hah a
eisen@PVGN34701109A:/tmp> eval 'VAR1="hah   a"';echo $VAR1
hah a

我自己找不到解决办法。请提供帮助,如果有任何其他更好的方法来拆分一行并分配给 BASH 中的变量,请分享您的想法。提前致谢。

我建议使用 shell 数组来存储单个字段值,并且 awk 略有不同:

IFS=$'' read -ra arr < <(awk -F'#\$' -v OFS='' '{=}1' file)

# check array content
declare -p arr

declare -a arr='([0]="hah   a" [1]="hehe" [2]="hoho")'

我们使用控制字符 </code> 作为输出字段分隔符,并在 <code>IFS 中使用相同的字符来在 </code> 上创建 <code>read 拆分字段。


您也可以使用 sed 代替 awk

IFS=$'' read -ra arr < <(sed 's/#$/\x03/g' file)

在 BASH ver 4+

中使用 NUL 字节
readarray -d $'[=12=]' arr < <(
awk -F'#\$' -v OFS='[=12=]' '{ORS=OFS; =} 1' file)
#!/bin/bash

getVar(){ 
    if [ "" -eq 0 ]; then  
        awk -F'#\$' '{for(i=1; i<=NF; i++) print $(i)}' file.txt;
    else
        awk -F'#\$' -v col="" '{printf $(col)}' file.txt;
    fi
} 

# assign variables
VAR1=$(getVar 1)
VAR2=$(getVar 2)
VAR3=$(getVar 3)
# using variables
echo "VAR1 ===${VAR1}==="
echo "VAR2 ===${VAR2}==="
echo "VAR3 ===${VAR3}==="
echo

# declare array
readarray -t my_array < <(getVar 0)
# dump
declare -p my_array|sed 's/declare -a //'
# using variables
echo "VAR1 ===${my_array[0]}==="
echo "VAR2 ===${my_array[1]}==="
echo "VAR3 ===${my_array[2]}==="

输出

VAR1 ===hah   a===
VAR2 ===hehe===
VAR3 ===hoho===

my_array=([0]="hah   a" [1]="hehe" [2]="hoho")
VAR1 ===hah   a===
VAR2 ===hehe===
VAR3 ===hoho===