ram*_*rur 17 arrays bash newline
我有这个脚本 -
nmapout=`sudo nmap -sP 10.0.0.0/24`
names=`echo "$nmapout" | grep "MAC" | grep -o '(.\+)'`
echo "$names"
Run Code Online (Sandbox Code Playgroud)
现在$names变量包含用换行符分隔的字符串 -
>_
(Netgear)
(Hon Hai Precision Ind. Co.)
(Apple)
Run Code Online (Sandbox Code Playgroud)
我尝试用子串方法进行数组转换 -
names=(${names//\\n/ })
echo "${names[@]}"
Run Code Online (Sandbox Code Playgroud)
但问题是${names[$i],如果我运行此循环,我无法通过索引(即等)访问它们-
for (( i=0; i<${#names[@]}; i++ ))
do
echo "$i: ${names[$i]"
# do some processing with ${names[$i]}
done
Run Code Online (Sandbox Code Playgroud)
我得到这个输出 -
>_
0: (Netgear)
1: (Hon
2: Hai
Run Code Online (Sandbox Code Playgroud)
但我想要的是 -
>_
0: (Netgear)
1: (Hon Hai Precision Ind. Co.)
2: (Apple)
Run Code Online (Sandbox Code Playgroud)
我无法找到一个好方法,请注意第二个字符串中有空格.
任何的想法 ?
小智 27
设置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
Run Code Online (Sandbox Code Playgroud)
产量
0: Netgear
1: Hon Hai Precision Ind. Co.
2: Apple
Run Code Online (Sandbox Code Playgroud)
Ale*_*Ale 19
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"
Run Code Online (Sandbox Code Playgroud)
该-t选项删除分隔符 ( '\n'),以便它可以显式添加到printf. 输出是:
0: Netgear
1: Hon Hai Precision Ind. Co.
2: Apple
Run Code Online (Sandbox Code Playgroud)
fir*_*iku 11
让我为Sanket Parmar的回答做出贡献.如果您可以将字符串拆分和处理提取到单独的函数中,则无需保存和恢复$IFS- 请local改为使用:
#!/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"
Run Code Online (Sandbox Code Playgroud)
也可以看看:
Bashshellcheck静态代码分析器和检查器工具建议在 SC2206 中使用read -r或mapfile。他们的mapfile示例是完整的,但他们的read示例仅涵盖了按空格而不是换行符分割字符串的情况,因此我从@Toni Dietze 的评论中read了解了用于此目的的命令的完整形式。
因此,以下是如何使用两者来按换行符分割字符串。请注意,这<<<称为“herestring”。它类似于“ <<heredoc ”,并且<读取文件:
# split the multiline string stored in variable `var` by newlines, and
# store it into array `myarray`
# Option 1
# - this technique will KEEP empty lines as elements in the array!
# ie: you may end up with some elements being **empty strings**!
mapfile -t myarray <<< "$multiline_string"
# OR: Option 2 [my preference]
# - this technique will NOT keep empty lines as elements in the array!
# ie: you will NOT end up with any elements which are empty strings!
IFS=$'\n' read -r -d '' -a myarray <<< "$multiline_string"
Run Code Online (Sandbox Code Playgroud)
还有我最常使用的第三种技术,它不一定是shellcheck推荐的,但如果你正确使用它,它就很好,并且比上面的任何一个选项都更具可读性。eRCaGuy_dotfiles/useful_scripts我在我的目录中的许多脚本中使用它。克隆该存储库并grep -rn "IFS"在其中运行以查找我使用该技术的所有位置。
请参阅此处,了解我第一次了解到这一点的地方:@Sanket Parmar 的回答:将多行字符串转换为数组。
这里是:
# Option 3 [not necessarily recommended by shellcheck perhaps, since you must
# NOT use quotes around the right-hand variable, but it is **much
# easier to read**, and one I very commonly use!]
#
# Convert any multi-line string to an "indexed array" of elements:
#
# See:
# 1. "eRCaGuy_dotfiles/useful_scripts/find_and_replace.sh" for an example
# of this.
# 1. *****where I first learned it: https://stackoverflow.com/a/24628676/4561887
SAVEIFS=$IFS # Save current IFS (Internal Field Separator).
IFS=$'\n' # Change IFS (Internal Field Separator) to the newline char.
# Split a long string into a bash "indexed array" (via the parenthesis),
# separating by IFS (newline chars); notice that you must intentionally NOT use
# quotes around the parenthesis and variable here for this to work!
myarray=($multiline_string)
IFS=$SAVEIFS # Restore IFS
Run Code Online (Sandbox Code Playgroud)
read:查找目录中非目录本身的所有文件正如其他人所说,IFS 会帮助你。IFS=$'\n' read -ra array <<< "$names"
如果您的变量有带空格的字符串,请将其放在双引号之间。现在您可以通过以下方式轻松获取数组中的所有值${array[@]}