bash: convert '\\n' delimited strings into

2019-03-18 06:56发布

问题:

I have this script --

nmapout=`sudo nmap -sP 10.0.0.0/24`
names=`echo "$nmapout" | grep "MAC" | grep -o '(.\+)'`
echo "$names"

now the $names variable contains strings delimited with newlines --

>_
 (Netgear)
 (Hon Hai Precision Ind. Co.)
 (Apple)

I tried to do the array conversion with the sub-string approach --

names=(${names//\\n/ })
echo "${names[@]}"

But the problem is that I can't access them by indexing (i.e. ${names[$i] etc), if I run this loop --

for (( i=0; i<${#names[@]}; i++ ))
do
     echo "$i: ${names[$i]"
     # do some processing with ${names[$i]}
done

I get this output --

>_
 0: (Netgear)
 1: (Hon
 2: Hai

but what I want is --

>_
 0: (Netgear)
 1: (Hon Hai Precision Ind. Co.)
 2: (Apple)

I could not figure out a good way to do this, please note that the second string has spaces in it.

Any idea ?

回答1:

Set IFS. Shell uses IFS variable to determine what the field separators are. By default IFS is set to the space character. Change it to newline.

#!/bin/bash
names="Netgear
Hon Hai Precision Ind. Co.
Apple"

SAVEIFS=$IFS   # Save current IFS
IFS=$'\n'      # Change IFS to new line
names=($names) # split to array $names
IFS=$SAVEIFS   # Restore IFS

for (( i=0; i<${#names[@]}; i++ ))
do
    echo "$i: ${names[$i]}"
done

Output

0: Netgear
1: Hon Hai Precision Ind. Co.
2: Apple


回答2:

Let me contribute to Sanket Parmar's answer. If you can extract string splitting and processing into a separate function, there is no need to save and restore $IFS — use local instead:

#!/bin/bash

function print_with_line_numbers {
    local IFS=$'\n'
    local lines=($1)
    local i
    for (( i=0; i<${#lines[@]}; i++ )) ; do
        echo "$i: ${lines[$i]}"
    done
}

names="Netgear
Hon Hai Precision Ind. Co.
Apple"

print_with_line_numbers "$names"

See also:

  • Setting IFS for a single statement