将grep中的空白字符转换为数组

问题描述 投票:4回答:2

我开始的地方:

input="a s d f"
content=(`grep -o . <<< "$input"`)
echo ${#content[@]}
for ((a = 0; a < ${#content[@]}; a++)); do
    token="${content[a]}"
    echo "$token"
done
read -p ''

呼应:

4
a
s
d
f

虽然grep命令正在捕获空白,但是在构造数组时,空白字符正在丢失。大概是因为空格是定义数组时的分隔字符。

我想要的是:

content=({a,\ ,s,\ ,d,\ ,f})
echo ${#content[@]}
for ((a = 0; a < ${#content[@]}; a++)); do
    token="${content[a]}"
    echo "$token"
done
read -p ''

呼应:

7
a

s

d

f

数组长度为7,空格存储为自己的字符。这就是我想要的。但是,在这个例子中输入是硬编码的。我试图从任何输入字符串到达​​这一点。

是)我有的:

input="a s d f"
content=({`grep -o . <<< "$input" | sed 's/ /\\\ /g' | sed 's/.*/&,/g'`})
echo ${#content[@]}
for ((a = 0; a < ${#content[@]}; a++)); do
    token="${content[a]}"
    echo "$token"
done
read -p ''

呼应:

10
{a,
\
,
s,
\
,
d,
\
,
f,}

所以我尝试使用sed重新格式化grep输出的返回方式,这样就可以匹配我的第二个例子中的模式。正如你所看到的,这不符合我的预期。

我的问题:

如何在仍然使用输入变量来构造数组时,在第二个示例中获得结果?我只是犯了一个愚蠢的错误吗?这一般只是一种不好的方法吗?任何帮助,将不胜感激。

bash shell sed grep
2个回答
4
投票

首先想到的是(与<newline>一起使用):

input="a s d f"
content=()
for ((i=0; i<${#input}; i++)); do 
   content+=("${input:$i:1}")
done

echo ${#content[@]}
printf '%s\n' "${content[@]}"

输出:

7
a

s

d

f

其他方法(更短但这些将忽略<newline>中的任何$input):

set -f #to prevent globbing
old_IFS=$IFS
IFS=$'\n'
content=($(grep -o . <<< "$input"))
IFS=$old_IFS
IFS=$'\n' read -r -a content -d '' < <(grep -o . <<< "$input")
readarray -t content < <(grep -o . <<< "$input")

其他不会忽视<newline>的方法:

content=()
while IFS= read -r -d '' char; do
   content+=("$char")
done < <(grep -z -o . <<< "$input")
unset "content[${#content[@]}-1]" #trims the final newline

@EdMorton提出的更好版本的readarray(你需要bash 4.4)解决方案:

readarray -d '' -t content < <(grep -z -o . <<< "$input")
unset "content[${#content[@]}-1]" #trims the final newline

0
投票

您可以通过调整IFS来更改分词的工作方式,并且可以使用read -n 1捕获单个字符。例如:

$ input="a b c d"
$ while IFS= read -n 1 token; do echo "> _${token}_"; done <<<"$input"
> _a_
> _ _
> _b_
> _ _
> _c_
> _ _
> _d_
> __

显示最后一个空白,因为此处文本输入重定向(qazxsw poi)会在您提供的输入中附加换行符。

如果你想将这些字符存储在一个数组中,你可以随意追加,就像Pesa建议的那样......

<<<

我们现在可以从数组中删除最终的换行符:

$ declare -a content=()
$ while IFS= read -n 1 token; do content+=("$token"); done <<<"$input"
$ declare -p content
declare -a content=([0]="a" [1]=" " [2]="b" [3]=" " [4]="c" [5]=" " [6]="d" [7]="")

从那里,您可以使用printf格式化输出,但是您可以使用数组来提供内容:

unset content[$((${#content[@]}-1))]
© www.soinside.com 2019 - 2024. All rights reserved.