在bash脚本中,
我有一个包含几个单词的字符串,这些单词用一个或多个空格分隔。即:
Name Age Sex ID Address
如果我想找到任何一个单词,例如,我想找到单词“ Age”的索引,该怎么办?
是否有任何命令可以直接返回我想要的单词的索引号?
谢谢。
在bash脚本中,
我有一个包含几个单词的字符串,这些单词用一个或多个空格分隔。即:
Name Age Sex ID Address
如果我想找到任何一个单词,例如,我想找到单词“ Age”的索引,该怎么办?
是否有任何命令可以直接返回我想要的单词的索引号?
谢谢。
Answers:
Bash仅靠字符串本身就执行字符串拆分操作 -实际上,经常会避免这种情况,避免引用是一个问题,而且引号的原因非常重要。在您的情况下,很容易利用它:只需将字符串放入数组中而不用引号将其括起来– bash将使用分词来分隔各个元素。假设您的字符串存储在变量中$str
,
ar=($str) # no quotes!
将返回5个元素的数组。数组索引是单词索引(像大多数脚本和编程语言一样,从0开始计数),即使用以下命令访问“年龄”
${ar[1]} # 0 => Name, 1 => Age, 2 => Sex, 3 => ID, 4 => Address
或者,如果您需要按内容查找元素索引,请遍历数组,即
function el_index {
cnt=0; for el in "${ar[@]}"; do
[[ $el == "$1" ]] && echo $cnt && break
((++cnt))
done
}
el_index "Age" # => 1
$ export FOO="Name Age Sex ID Address"
将*年龄替换为年龄-删除“年龄”之前的所有内容:
$ echo ${FOO/*Age/Age}
Age Sex ID Address
在“年龄”之前获取任何东西
$ echo ${FOO/Age*/}
Name
获取该字符串的长度(这是“年龄”的索引):
$ BEGIN=${FOO/Age*/}
$ echo ${#BEGIN}
7
export L='debug info warn error'; export GTE='warn'; echo ${L/*${GTE}/${GTE}}
打印“警告错误”
您可以使用bash的本机正则表达式
# a function to print the index of a field and its name
printIx() {
for ((l=0,i=1;i<$1;i++)) ;do
((l+=${#BASH_REMATCH[i]}))
done
printf '%3s %s\n' $l "$2"
}
# Using a zero based index
# "0----+----1----+----2----+----3----+----4"
str=" Name Age Sex ID Address "
if [[ $str =~ ^(\ *)(Name)(\ +)(Age)(\ +)(Sex)(\ +()ID)(\ +)(Address)\ *$ ]] ;then
F=(Name Age Sex ID Address)
f=( 2 4 6 8 10) # regex back-references
for ((g=0;g<${#f[@]};g++)) ;do
printIx ${f[g]} "${F[g]}"
done
fi
输出量
2 Name
9 Age
13 Sex
20 ID
29 Address
注意:此处假设通过索引表示您要知道它是哪个单词(从0开始),而不是该单词从字符串中的哪个字符开始。其他答案针对后者。
不是我知道的,但是您可以做到。两个技巧:
码:
#!/bin/bash
find_index() {
local str=$1
local search=$2
let local n=0
local retval=1 # here, 1 is failure, 0 success
for col in $str; do # $str unquoted -> whitespace tokenization!
if [ $col = $search ]; then
echo $n
retval=0
break
else
((n++))
fi
done
return $retval
}
test="Name Age Sex ID Address"
idx=`find_index "$test" Age`
if [ $? -ne 0 ]; then
echo "Not found!"
else
echo "Found: $idx"
fi
在shell中尝试以下javascript oneliner(使用javascript shell):
$ js <<< "x = 'Name Age Sex ID Address'; print(x.indexOf('Age'));"
7
或使用此处文档:
js <<EOF
x = 'Name Age Sex ID Address';
print(x.indexOf('Age'));
EOF
我找到了一个行之有效的解决方案。
$ string ='现在是时间'
$ buf = the $ {string#* the}
$ echo $ buf
输出:时间
$ index = $((($ {#string}-$ {#buf} + 1))
$ echo $ index
输出:8->第一个单词“ the”的索引
它的工作原理类似于Java中的indexOf()函数,该函数返回第一次出现的输入字符串。
在这里http://www.linuxquestions.org/questions/linux-newbie-8/bash-string-manipulation-help-670627/中找到了该解决方案(最新文章)。这个家伙救了我一天。归功于他。
如果要从第一个indexof开始做子字符串,更快的方法。
$ a =“某些长字符串”
$ b =“ ri”
$ echo $ {a / * $ b / $ b}
ring
$ echo $ {a / $ b * / $ b}
一些long stri
/programming/10349102/shell-script-substring-from-first-indexof-substring
如果coreutils可用,则可以通过以下方式进行:
回声$ {str / Age //} | 切-d / -f1 | wc -w
根据MariusMatutiae的要求,我要添加一个解释,说明这三步操作的工作原理:
echo $ {str / Age //} 1.替换正在搜索的字符串以查找唯一字符(在我的情况下为/)
cut -d / -f1 2.截断字符串的整个部分,该部分在唯一的char之后
wc -w 3.计算并打印剩下的单词,这将给我们一个索引号
有关参考,请检查:
http://www.tldp.org/LDP/abs/html/parameter-substitution.html(转到:“变量扩展/子字符串替换”)
http://www.gnu.org/software/coreutils/manual/coreutils .html(转到:“剪切命令”和“ wc调用”
使用纯bash数组和子字符串替换混合使用两个先前给出的答案。
这个想法是在想要的单词之前获取所有单词的字符串,然后通过将其分成数组来计算该子字符串中的单词数。
$ haystack="Name Age Sex ID Address"
$ words_before=( ${haystack%Age*} ) # truncate string, make array
$ echo ${#words_before[*]} # count words in array
1
当然Age可以存储在另一个变量中needle
,然后使用${haystack%$needle*}
。如果您搜索的单词是另一个单词的子集,则可能会遇到问题,在这种情况下,kopischke的答案仍然有效。