简体   繁体   中英

Iterating over a string separated by unescaped characters only

Say I have the following string:

var="One two three\ four five"

What command would have the following code:

for item in "$(operation on $var)"; do
  echo "$item"
done

and produce the following output:

One
two
three four
five

Alternatively, could I use single quotes to achieve this on a string input that is already wrapped in double quotes? Ie, could I have the string

var="One two 'three four' five"

produce the same output under the above conditions?

You may use gnu grep in perl mode:

var="One two three\ four five"
grep -oP '[^\s\\]+(\\.[^\s\\]+)*' <<< "$var"

Regex Details:

  • [^\\s\\\\]+ : Match 1+ of any non-whitespace character that is not \\
  • ( : Start group
    • \\\\.[^\\s\\\\]+ : Match \\ followed by any escaped character followed by another string containing 1+ non-whitespace and non-backslash characters.
  • )* : End group. Match 0 or more of this group.

One
two
three\ four
five

Here is posix version of same grep :

grep -oE '[^\\[:blank:]]+(\\.[^\\[:blank:]]+)*' <<< "$var"

If you want to loop through these strings in a loop:

while IFS= read -r str; do
   echo "$str"
done < <(grep -oP '[^\s\\]+(\\.\S+)*' <<< "$var")

Just to extend off of anubhava's thorough answer for the first case ( "\\ " ), here's the answer for the second case ( "' '" ):

echo "one two 'three four three and a half' five" | 
  grep -oE "('([^'[:blank:]]+ )+[^'[:blank:]]+'|[^'[:blank:]]+)"

outputs:

one
two
'three four three and a half'
five

Use an array:

arr=(one two 'three four' five)
for item in "${arr[@]}" ; do
    echo "$item"
done

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