tr_mine AB DC
我想有两个数组:a [0] = A,a [1] = B和b [0] = C b [1] = D.
我找到了一种方法,但它无效:
IFS="" read -r -a array <<< "$a"
答案 0 :(得分:2)
没有sed,没有awk,所有bash internals。
假设单词总是用空格(空格和/或制表符)分隔,
还假设单词作为参数给出,并仅为bash编写:
#!/bin/bash
blank=$'[ \t]'
varname='A'
n=1
while IFS='' read -r -d '' -N 1 c ; do
if [[ $c =~ $blank ]]; then n=$((n+1)); continue; fi
eval ${varname}${n}'+=("'"$c"'")'
done <<<"$@"
last=$(eval echo \${#${varname}${n}[@]}) ### Find last character index.
unset "${varname}${n}[$last-1]" ### Remove last (trailing) newline.
for ((j=1;j<=$n;j++)); do
k="A$j[@]"
printf '<%s> ' "${!k}"; echo
done
这会将每个数组A1,A2,A3等......设置为每个单词的字母。
$n
的第一个循环结束时的值是处理的单词数。
打印可能有点棘手,这就是上面给出访问每个字母的代码的原因。
应用于您的示例文本:
$ script.sh AB DC
<A> <B>
<D> <C>
该脚本正在设置两个(数组)变量A1
和A2
每个字母是一个数组元素:A1 [0] = A,A1 [1] = B和A2 [0] = C,A2 [1] = D.
您需要将变量($k
)设置为要访问的数组元素
例如,您需要做echo
第二个字(基于1)的第四个字母(基于0)(如果需要可以更改):
k="A2[3]"; echo "${!k}" ### Indirect addressing.
该脚本将按以下方式工作:
$ script.sh ABCD efghi
<A> <B> <C> <D>
<e> <f> <g> <h> <i>
警告:即使引用,也会拆分字符。但是,引用的参数是使用此脚本来避免shell元字符(|,&amp;,;,(,),&lt;,&gt;,space,tab)的影响的正确方法。当然,空格(即使重复)会分割由变量$blank
定义的单词:
$ script.sh $'qwer;rttt fgf\ngfg'
<q> <w> <e> <r> <;> <r> <t> <t> <t>
<>
<>
<>
<f> <g> <f> <
> <g> <f> <g>
由于脚本将接受并正确处理已嵌入的换行符,我们需要使用:unset "${varname}${n}[$last-1]"
删除最后一个跟踪&#34;换行符&#34;。如果不需要,请引用该行。
安全提示:此处的评估不是问题,因为它一次只处理一个字符。仅基于一个角色创建攻击是很困难的。无论如何,通常的警告是有效的:在使用此脚本之前始终清理您的输入。此外,bash的大多数(未引用的)元字符都会破坏此脚本。
$ script.sh qwer(rttt fgfgfg
bash: syntax error near unexpected token `('
答案 1 :(得分:0)
如果可能的话,我强烈建议用另一种语言来做这件事,这会更容易。
现在,我最接近的是:
#!/bin/bash
sentence="AC DC"
words=`echo "$sentence" | tr " " "\n"`
# final array
declare -A result
# word count
wc=0
for i in $words; do
# letter count in the word
lc=0
for l in `echo "$i" | grep -o .`; do
result["w$wc-l$lc"]=$l
lc=$(($lc+1))
done
wc=$(($wc+1))
done
rLen=${#result[@]}
echo "Result Length $rLen"
for i in "${!result[@]}"
do
echo "$i => ${result[$i]}"
done
以上版画:
Result Length 4
w1-l1 => C
w1-l0 => D
w0-l0 => A
w0-l1 => C
说明:
result
)w
表示单词,l
表示字母。这将使进一步处理变得痛苦...... ${!result[@]}
代替${result[@]}
。第一个迭代键,第二个迭代值我知道这不是你要求的,但我希望它会指出你正确的方向
答案 2 :(得分:0)
试试这个:
sentence="$@"
read -r -a words <<< "$sentence"
for word in ${words[@]}; do
inc=$(( i++ ))
read -r -a l${inc} <<< $(sed 's/./& /g' <<< $word)
done
echo ${words[1]} # print "CD"
echo ${l1[1]} # print "D"
第一个read
读取所有单词,内部单词用于字母。
sed命令在每个字母后面添加一个空格,以使字符串可由read -a
拆分。您也可以使用此sed命令在拆分之前从单词(例如逗号)中删除不需要的字符。
如果单词中允许使用特殊字符,则可以使用简单的grep而不是sed命令(如http://www.unixcl.com/2009/07/split-string-to-characters-in-bash.html中所示):
read -r -a l${inc} <<< $(grep -o . <<< $word)
单词数组是${w}
。
字母数组名为l#
,其中#是为每个单词读取添加的增量。