bashshellvariable-substitution

Linux bash; manipulate PATH type var


Linux debian bash. I have a PATH type variable 'X' that I want to manipulate. 'X' can be any number of elements delimited by ":" For example, using fruits:

set X=apple:pear:orange:cherry

How might I extract the first element minus its delimiter, saving it into a new variable 'Y', and then remove it and its delimiter from 'X'. As in..

apple:pear:orange:cherry

becomes

Y=apple X=pear:orange:cherry

I have looked at bash substitution cheat sheets, but it's mind boggling. Sed is also a way, but I can never seem to get rid of the delimiters.

I did get this far

IFS=: arr=($X)
Y=${arr[0]}
cnt=${#arr[@]}
IFS=

Which isn't very far, but at least I get Y but it doesn't do anything with X. To be honest, I dont understand them anyway , just used a cheat sheet. So explanations with solutions would be appreciated.


Solution

  • You could:

    X=apple:pear:orange:cherry
    IFS=: read -r Y X <<<"$X"    # note - will fail with newlines
    declare -p Y X
    # declare -- Y="apple"
    # declare -- X="pear:orange:cherry"
    

    read will assign the first element to Y and then the rest to X. For more information, see documentation of read and of your shell, in particular man 1p read and bash manual and POSIX read.

    But using arrays with splitting would be fine too. Fun fact - it can be one line.

    X=apple:pear:orange:cherry
    IFS=:
    arr=($X)
    Y=${arr[0]}
    X="${arr[*]:1}"
    declare -p Y X
    # declare -- Y="apple"
    # declare -- X="pear:orange:cherry"
    

    ($X) will do word splitting expansion and assign an array. With ${arr[0] the first element is extracted. The arr[*] joins the array elements using first character in IFS and using ${ :1} expansion all elements except the first are extracted, see shell parameter expansions.