First I was using IFS and read, but then I found -- IFS can only support single character as separator and sometimes I need a string to be the separator. Then, I was thinking maybe use awk and eval can do it. So I have a try --
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
At first, I think it's fine. But immediately I found the issue -- in file1, the first value should be "hah a" -- there's 3 space inside, But after awk and eval -- there's only one space left... Then I tested with awk and eval individually, I found it's due to the eval will "eat" some space--
eisen@PVGN34701109A:/tmp> eval "VAR1='hah a'";echo $VAR1
hah a
eisen@PVGN34701109A:/tmp> eval 'VAR1="hah a"';echo $VAR1
hah a
I can't find solution myself. Please kind help and if there's any other better way to split one line and assign to variables in BASH, please share your idea. Thanks in advance.
CodePudding user response:
I would suggest using shell arrays for storing individual field values and slightly different awk
for this:
IFS=$'\03' read -ra arr < <(awk -F'#\\$' -v OFS='\03' '{$1=$1}1' file)
# check array content
declare -p arr
declare -a arr='([0]="hah a" [1]="hehe" [2]="hoho")'
We are using control character \03
as output field separator and using same in IFS
to make read
split fields on \03
.
Alternatively you can use sed
instead of awk
also:
IFS=$'\03' read -ra arr < <(sed 's/#\$/\x03/g' file)
Using a NUL byte with BASH ver 4
readarray -d $'\0' arr < <(
awk -F'#\\$' -v OFS='\0' '{ORS=OFS; $1=$1} 1' file)
CodePudding user response:
#!/bin/bash
getVar(){
if [ "$1" -eq 0 ]; then
awk -F'#\\$' '{for(i=1; i<=NF; i ) print $(i)}' file.txt;
else
awk -F'#\\$' -v col="$1" '{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]}==="
output
VAR1 ===hah a===
VAR2 ===hehe===
VAR3 ===hoho===
my_array=([0]="hah a" [1]="hehe" [2]="hoho")
VAR1 ===hah a===
VAR2 ===hehe===
VAR3 ===hoho===