For example, with the string a_link_list_java, use the _ character to separate the string in half would result in: a_link_list and java.

list_java would result in: list and java.

I want to take these two parts and store them into two variables.

I tried the cut command but it only works for only one character shown in the string

How can I accomplish this in a bash shell script?


The shell's parameter expansions can do that:

$ v="a_link_list_java"
$ printf "%s\n" "${v%_*}" "${v##*_}"

Though note that if the patterns in the expansion don't match, nothing is removed. So a value without an underscore would be unchanged by both transformations:

$ v=foo
$ printf "%s\n" "${v%_*}" "${v##*_}"

With sed:

var1=$(sed 's/_[^_]*$//' file)
var2=$(sed 's/.*_//' file)

Notice that sed is very greedy, so in the second case glob * swallows all characters, including previous underscores _.


$ echo "$var1"
$ echo "$var2"

Using awk you can have all in separate defining delimiter as _

VAR1=$(awk -F'_' '{print $1}' infile.txt) 

You can print which fields you want based on its index above instead of $1 that points to first field.

Or you can use bash and read as an array.

IFS='_' read -r -a array <<< "$myString"

then simply read with individual index number:

echo "${array[2]}"

Or even simply you can use bash parameter expansion:

VAR1="${myString%_*}"   # will gives you 'a_link_list' 
VAR2="${myString##*_}"  # will gives you 'java' 
VAR3="${VAR1%_*}"       # will gives you 'a_link' 
  • for example a_link_list_java , i want my first field to be a_link_list , not a, Because I do not know about how many '_' would contain in the string
    – JohnnyP
    Aug 3 '17 at 19:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.