简体   繁体   中英

regex usage in shell script

With the shell script in Section-A I'm getting the output as shown in Section-B. However the expected/desired output is as shown in Section-C. Need help in modifying the code to get the desired output.

Section-A: Shell Script

#!/usr/local/bin/bash

i=0
a="1234-A1;1235-A2;2345-B1;5678-C2;2346-D5"

IFS="[;]" read -r -a arr <<< "1234-A1;1235-A2;2345-B1;5678-C2;2346-D5"
#printf '%s\n' "${arr[@]}"

for chip in "${arr[@]}"
do
    echo " var $((i++)) is : $chip"
done

Section-B: Output of above code

 var 0 is : 1234-A1
 var 1 is : 1235-A2
 var 2 is : 2345-B1
 var 3 is : 5678-C2
 var 4 is : 2346-D5

Section-C: Desired Output is:

var 0 is : 1234 and version is A1
var 1 is : 1235 and version is A2
var 2 is : 2345 and version is B1
var 3 is : 5678 and version is C2
var 4 is : 2346 and version is D5

As a general way to approach splitting a value with a regex, even though not the only (or best) way to achieve the desired result in this case, you can to it like this :

#!/bin/bash

a="1234-A1;1235-A2;2345-B1;5678-C2;2346-D5"
declare -i i=0

IFS=";" read -a records <<<"$a"

for record in "${records[@]}"
do
  [[ $record =~ (.*)-(.*) ]] || continue
  echo "var $((i++)) is ${BASH_REMATCH[1]} and version is ${BASH_REMATCH[2]}"
done

Any reason you don't simply initialize the associative array directly from the values you have?

#!/bin/bash

declare -rgA arr=([1234]=A1 [1235]=A2 [2345]=B1 [5678]=C2 [2346]=D5)

i=0
for chip in "${!arr[@]}"
do
    echo "var $((i++)) is $chip and version is ${arr[$chip]}"
done

Demo: http://ideone.com/Ef9T9P

(The nature of associative arrays is such that the values will often not be printed in the order you put them in. Maybe use two regular arrays instead if this is a major problem.)

You can achieve the desired result by using both the field separator ( IFS ) and the delimiter option of read , using only one read command.

#!/bin/bash

a="1234-A1;1235-A2;2345-B1;5678-C2;2346-D5;"
declare -i i=0

while IFS="-" read -d ";" -r chip version
do
  echo "var $((i++)) is $chip and version is $version"
done <<<"$a"

This treats a semi-colon as a record separator, and IFS as how to split fields inside a record. Two variables are read by read for each record.

Please note you need to add a trailing semi-colon in the data, or the last record will be discarded.

#!/usr/local/bin/bash

i=0
a="1234-A1;1235-A2;2345-B1;5678-C2;2346-D5"

IFS="[;]" read -r -a arr <<< "1234-A1;1235-A2;2345-B1;5678-C2;2346-D5"
#printf '%s\n' "${arr[@]}"

for chip in "${arr[@]}"
do
    echo " var $((i++)) is : $chip"
    echo "var $((i++)) is : ${chip%-*} and version is ${chip#*-}"
done

Output:

var 0 is : 1234 and version is A1
var 1 is : 1235 and version is A2
var 2 is : 2345 and version is B1
var 3 is : 5678 and version is C2
var 4 is : 2346 and version is D5

I'm not sure if the use of an array is a pre requisite. If it isn't, a quck one line solution would be:

echo $a | tr ";" "\n" | awk -F\- '{ print "var "NR" is : "$1" and version is "$2 }' 

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