如何在bash中找到字符串中单词的索引?


10

在bash脚本中,

我有一个包含几个单词的字符串,这些单词用一个或多个空格分隔。即:

Name   Age Sex  ID         Address

如果我想找到任何一个单词,例如,我想找到单词“ Age”的索引,该怎么办?

是否有任何命令可以直接返回我想要的单词的索引号?

谢谢。


解决方案必须严格遵守bash吗?还是可以使用awk,grep等?
jftuga 2012年

Answers:


12

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

哇...我不知道没有引号就不会是数组。谢谢!
2012年

4
$ 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

没有回答问题,但是哇!狡猾的把戏。它甚至可以在ash中运行,并带有嵌入式变量:export L='debug info warn error'; export GTE='warn'; echo ${L/*${GTE}/${GTE}}打印“警告错误”
Steve Tarver

0

如果您不必严格使用bash,但是可以使用带有bash的系统上常见的其他程序,则可以使用以下方法:

echo "Name   Age Sex ID  Addr" | python -c 'print(raw_input().index("Age"))+1'

Python的字符串索引从零开始,因此我在命令末尾添加了+1。


0

您可以使用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

注意:此处假设通过索引表示您要知道它是哪个单词(从0开始),而不是该单词从字符串中的哪个字符开始。其他答案针对后者。

不是我知道的,但是您可以做到。两个技巧:

  1. 使用for构造函数的先天能力将空白的未引用输入分割开。
  2. 处理无法找到所需列的情况。在这种情况下,我选择将找到的索引发送到stout,并让状态代码指示查找是否成功。还有其他可能性。

码:

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

0

在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

0

我找到了一个行之有效的解决方案。

$ 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


0

如果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调用”


虽然这解决了手头的问题,但这些站点却不那么简洁。花几句话确切地解释为什么这样做会更有帮助。请这样做。
MariusMatutiae 2014年

0

使用纯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的答案仍然有效。


0

这是一个已有7年历史的问题,但有些人可能需要纯正的答案。

STRING="Name   Age Sex  ID         Address"
INDEXOF_AGE=${#${STRING/Age*/}}
echo $INDEXOF_AGE
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.