Как найти индекс слова в строке в bash?


10

В скрипте bash,

У меня есть строка, которая содержит несколько слов, разделенных одним или несколькими пробелами. то есть:

Name   Age Sex  ID         Address

Если я хочу найти какое-либо слово, например, я хочу найти индекс слова «Возраст», как я могу это сделать?

Есть ли какая-нибудь команда, которая будет возвращать порядковый номер слова, которое я хочу напрямую?

Спасибо.


Решение должно быть строго в bash? Или можно использовать awk, grep и т. Д.?
Jftuga

Ответы:


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

вау ... я не знал, что без кавычек тогда это будет массив. Спасибо!
G3Y

4
$ export FOO="Name   Age Sex  ID         Address"

Замените * Age with Age - это удалит что-либо до "Age":

$ 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}}выводит сообщение «error error»
Стив Тарвер,

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. Используйте врождённые способности для конструкции дробить в кавычках ввода пробелов.
  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

Попробуйте следующий oneliner javascript в оболочке (используйте оболочку javascript):

$ 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 = вывод $ {string # * the}
$ echo $ buf
: время
$ index = $ (($ {# string} - $ {# buf} + 1))
$ echo $ index
output: 8 -> index первого слова "the"

Он работает аналогично функции indexOf () в Java, которая возвращает первое вхождение входной строки.

Нашел это решение здесь 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}
некоторая длинная полоса

/programming/10349102/shell-script-substring-from-first-indexof-substring


0

Если доступны coreutils, вы можете сделать это следующим образом:

echo $ {str / Age //} | cut -d / -f1 | туалет

В соответствии с запросом MariusMatutiae я добавляю объяснение, как работает эта трехэтапная операция:

echo $ {str / Age //} 1. заменить строку, в которой ищется уникальный символ (в моем случае /)

cut -d / -f1 2. отрезать целую часть строки после уникального символа

wc -w 3. подсчитать и напечатать слова, которые остались, это даст нам порядковый номер

Для ссылок, пожалуйста, проверьте:

http://www.tldp.org/LDP/abs/html/parameter-substitution.html (см. «Расширение переменной / замена подстроки»)
http://www.gnu.org/software/coreutils/manual/coreutils .html (перейти к: «Команда вырезания» и «вызов wc»


Хотя это решает проблему, такие краткие ответы не одобряются на этих сайтах. Было бы более полезно потратить несколько слов, объясняющих, почему это работает. Пожалуйста, сделай так.
MariusMatutiae

0

Сочетание двух ранее заданных ответов с использованием чистых массивов bash и замены подстрок.

Идея состоит в том, чтобы получить строку всех слов перед тем, которое вы хотите, а затем подсчитать количество слов в этой подстроке, превратив ее в массив.

$ haystack="Name   Age Sex  ID         Address"
$ words_before=( ${haystack%Age*} )     # truncate string, make array
$ echo ${#words_before[*]}              # count words in array
1

Конечно, возраст можно сохранить в другой переменной needle, а затем использовать ${haystack%$needle*}. Ожидайте проблем, если искомое слово является подмножеством другого слова, и в этом случае ответ Копишке все еще работает.


0

Это 7-летний вопрос, но некоторые могут нуждаться в ответе в чистом виде.

STRING="Name   Age Sex  ID         Address"
INDEXOF_AGE=${#${STRING/Age*/}}
echo $INDEXOF_AGE
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.