bash:将 '\n' 分隔的字符串转换为数组

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24628076/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 00:54:58  来源:igfitidea点击:

bash: convert '\n' delimited strings into array

arraysbashnewline

提问by ramgorur

I have this script --

我有这个脚本——

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

now the $namesvariable contains strings delimited with newlines --

现在$names变量包含用换行符分隔的字符串——

>_
 (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 --

但问题是我无法通过索引(即${names[$i]等)访问它们,如果我运行这个循环——

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 ?

任何的想法 ?

回答by Sanket Parmar

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

设置IFS。Shell 使用IFS变量来确定字段分隔符是什么。默认IFS设置为空格字符。将其更改为换行符。

#!/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

回答by firegurafiku

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 localinstead:

让我为Sanket Parmar 的回答做出贡献。如果您可以将字符串拆分和处理提取到单独的函数中,则无需保存和恢复$IFSlocal而是使用:

#!/bin/bash

function print_with_line_numbers {
    local IFS=$'\n'
    local lines=()
    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:

也可以看看:

回答by Ale

Bash also has a readarraybuiltin command, easily searchable in the man page. It uses newline (\n) as the default delimiter, and MAPFILEas the default array, so one can do just like so:

Bash 还有一个readarray内置命令,可以在手册页中轻松搜索。它使用换行符 ( \n) 作为默认分隔符和MAPFILE默认数组,因此可以这样做:

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

    readarray -t <<<$names

    printf "0: ${MAPFILE[0]}\n1: ${MAPFILE[1]}\n2: ${MAPFILE[2]}\n"

The -toption removes the delimiter ('\n'), so that it can be explicitly added in printf. The output is:

-t选项删除分隔符 ( '\n'),以便它可以显式添加到printf. 输出是:

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

回答by Hari Bharathi

As others said, IFS will help you.IFS=$'\n' read -ra array <<< "$names"if your variable has string with spaces, put it between double quotes. Now you can easily take all values in a array by ${array[@]}

正如其他人所说,IFS 会帮助你。IFS=$'\n' read -ra array <<< "$names"如果您的变量有带空格的字符串,请将其放在双引号之间。现在您可以通过以下方式轻松获取数组中的所有值${array[@]}