简体   繁体   中英

Save a newline separated list into several bash variables

I'm relatively new to shell scripting and am writing a script to organize my music library. I'm using awk to parse the id3 tag info and am generating a newline separated list like so:

Kanye West
College Dropout
All Falls Down

I want to store each field in a separate variable so I can easily compose some mkdir and mv commands. I've tried piping the output to IFS=$'\\n' read artist album title but each variable remains empty. I'm open to producing a different output from awk, but I still want to know how to parse a newline separated list using bash.

Edit:

It turns out that by piping directly to read by doing:

id3info "$filename" |  awk "$awkscript" | {read artist; read album; read title;}

WILL NOT WORK. It results in the variables existing in a different scope . I found that using a herestring works best:

{read artist; read album; read title;} <<< "$(id3info "$filename" |  awk "$awkscript")"

read normally reads one line at a time. So, if your id3 info is in the file testfile.txt , you can read it in as follows:

{ read artist ; read album ; read song ; } <testfile.txt
echo "artist='$artist' album='$album' song='$song'"
# insert your mkdir and mv commands....

When run on your test file, the above outputs:

artist='Kanye West' album='College Dropout' song='All Falls Down'

You can just read the file into a bash array and loop through the array like so:

IFS=$'\r\n' content=($(cat ${filepath}))
for ((idx = 0; idx < ${#content[@]}; idx+=3)); do
    artist=${content[idx]}
    album=${content[idx+1]}
    title=${content[idx+2]}
done

Or read three lines in a loop.

yourscript |
while read artist; do  # read first line of input
    read album         # read second line of input
    read song          # read third line of input
    : self-destruct if the genre is rap
done

This loop will consume input lines in groups of three. If there is not an even multiple of three lines of input, the reads after that inside the loop will simply fail and the variables will be empty.

You can read the output from awk into an array. Eg

readarray -t array <<< "$(printf '%s\n' 'Kanye West' 'College Dropout' 'All Falls Down')"
for ((i=0; i<${#array[@]}; i++ )) ; do
    echo "array[$i]=${array[$i]}"
done

Produces:

array[0]=Kanye West
array[1]=College Dropout
array[2]=All Falls Down

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM