I have the string below

/a585/app/data/CCN_text/CCN_split_files/ccn.email.list.file07 | /svr00c8/n585 | /a585/app/data/CCN_text | /a585/app/data/CCN_text | /a585/app/data/muttrc | | /a001/odbi_land/ondemand/download/scriptload | DVLP | cmodappl | ondemand

I am beginer to linux.how can i seperate by using "|" as delimeter and assign in a variable. I am passing the entrie string as parameter and need to split\cut the fields saperatly for example:

while read -r record; do
## here i need the fields to cut the fields and assign to a variable #####
done < $0 

bash -c function "/a585/app/data/CCN_text/CCN_split_files/ccn.email.list.file07 | /svr00c8/n585 | /a585/app/data/CCN_text | /a585/app/data/CCN_text | /a585/app/data/muttrc | | /a001/odbi_land/ondemand/download/scriptload | DVLP | cmodappl | ondemand"

when i tried the above example it trougths an error " $0: ambiguous redirect "

  • It makes little sense to separate and store in a variable. Unless it's an array; or multiple variables. Or do you want to change one separator into another (e.g. a newline)? Do you need the variable(s) in child process(es)? or only in Bash? What is your research so far and what have you tried? Is the string hardcoded? available in a file? in another variable? or generated by some tool? Please edit the question and be more specific about the usage case. – Kamil Maciorowski Feb 7 at 5:23
  • I need the variables in the child. i am passing the entire string to child and need to seperate and assign to variable. i have updated the question. – sai prudhvi Feb 7 at 5:55

You can use tr to separate using delimiter

In the following example we replace | by newline

variable=$(echo "/a585/app/data/CCN_text/CCN_split_files/ccn.email.list.file07 | /svr00c8/n585 | /a585/app/data/CCN_text | /a585/app/data/CCN_text | /a585/app/data/muttrc | | /a001/odbi_land/ondemand/download/scriptload | DVLP | cmodappl | ondemand" | tr "|" "\n")

echo $variable

You can also use

echo yourtext | tr -d "|"

See tr command

| improve this answer | |

So many issues beside the main one.

  1. ambiguous redirect is because your code lacks double-quotes.
  2. Redirection with < takes data from a file. Your string does not point to a file (path). In Bash you can take data from a string with <<<.
  3. function is a reserved word. There is a way to name a function function but its further use is inconvenient.
  4. (terminology in your comment) Function is not a child.
  5. One calls a function by its name, not with bash -c. My answer to your other question applies.
  6. Then the first argument is referred to as $1, not $0.

This code works, although I'm not sure it's exactly what you want:


split_string ()
   readarray -t arrayv < <(tr '|' '\n' <<< "$1")

split_string '/a585/app/data/CCN_text/CCN_split_files/ccn.email.list.file07 | /svr00c8/n585 | /a585/app/data/CCN_text | /a585/app/data/CCN_text | /a585/app/data/muttrc | | /a001/odbi_land/ondemand/download/scriptload | DVLP | cmodappl | ondemand'

# now arrayv is an array variable (indexed from 0)
# retrieving few values
echo "${arrayv[0]}"
echo "${arrayv[5]}"
echo "${arrayv[9]}"


  • You double-quoted the string. Remember a string in double-quotes undergoes certain expansions. Your string does not contain anything that would/could be expanded (e.g. $), so double-quotes are OK in this particular case. In general use single-quotes to suppress expansions.
  • readarray is a synonym for mapfile. Invoke help mapfile to learn.
  • Other research fodder: <<<, <( … ), arrays.
  • There is no way to export an array variable to the environment.
  • We could tell readarray to use | as delimiter:

     readarray -t -d '|' arrayv <<< "$1"

    but then the last "field" would include a trailing newline character (it would appear because of how <<< works). I turn all delimiters to newlines with tr, then readarray uses its default setting (newlines as delimiters).

  • Spaces don't belong to delimiters, they become parts of the stored values. Use sed instead of tr to turn substrings of delimiters with adjacent spaces into single newline characters. The readarray … line will be:

    readarray -t arrayv < <(sed 's/ *| */\n/g' <<< "$1")
  • If you're going to use the function just once, you don't need a function at all. This line (outside of any function) will do the job:

    readarray -t arrayv < <(tr '|' '\n' <<< '/a585/app/data/CCN_text/CCN_split_files/ccn.email.list.file07 | /svr00c8/n585 | /a585/app/data/CCN_text | /a585/app/data/CCN_text | /a585/app/data/muttrc | | /a001/odbi_land/ondemand/download/scriptload | DVLP | cmodappl | ondemand')

    I defined a function (and then used it just once) because you tried to define one.

  • If your input string consists of a fixed number of fields and the fields have meaning, it may be good to assign them to different (non-array, regular) variables whose names have meaning. Example:

    IFS='|' read -r path1 path2 path3 path4 path5 ip path6 wtf1 wtf2 wtf3 extra < <(sed 's/ *| */|/g' <<< '/a585/app/data/CCN_text/CCN_split_files/ccn.email.list.file07 | /svr00c8/n585 | /a585/app/data/CCN_text | /a585/app/data/CCN_text | /a585/app/data/muttrc | | /a001/odbi_land/ondemand/download/scriptload | DVLP | cmodappl | ondemand')
    echo "$ip"
    echo "$wtf3"

    Specific notes:

    • Here we explicitly use | as delimiter. When we use read, the trailing newline (that appears because of how certain redirections and tools work) is not only harmless, it's required.
    • I added the extra variable. If there are more fields than expected then the excessive fields will occupy extra. Without extra they would affect $wtf3.
    • You can export these variables.
  • If you're going to manipulate files/streams containing (many) records in a form of foo|bar|baz|… (or foo | bar | baz | … or similar) then get familiar with awk.

| improve this answer | |

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.