Bagaimana menemukan indeks kata dalam string di bash?

10

Dalam skrip bash,

Saya memiliki string yang berisi beberapa kata yang dipisahkan oleh satu atau lebih dari satu spasi. yaitu:

Name   Age Sex  ID         Address

Jika saya ingin menemukan salah satu kata, misalnya saya ingin menemukan indeks kata "Umur", bagaimana saya bisa melakukannya?

Apakah ada perintah yang akan mengembalikan nomor indeks kata yang saya inginkan secara langsung?

Terima kasih.

G3Y
sumber
Apakah solusinya harus benar-benar di bash? Atau bisakah awk, grep, dll digunakan?
jftuga

Jawaban:

12

Bash melakukan pemisahan kata dalam string dengan sendirinya - pada kenyataannya, lebih sering daripada tidak, menghindari itu adalah masalah, dan alasan mengutip sangat penting. Sangat mudah untuk meningkatkan itu dalam kasus Anda: cukup masukkan string Anda ke dalam array tanpa mengutipnya - bash akan menggunakan pemisahan kata untuk memisahkan elemen individual. Dengan asumsi string Anda disimpan dalam variabel $str,

ar=($str) # no quotes!

akan mengembalikan array 5 elemen. Indeks array Anda adalah indeks kata Anda (dihitung dari 0, seperti di sebagian besar bahasa scripting dan pemrograman), yaitu "Usia" diakses menggunakan

${ar[1]}  # 0 => Name, 1 => Age, 2 => Sex, 3 => ID, 4 => Address

atau, jika Anda perlu menemukan indeks elemen berdasarkan konten, loop di atas array, yaitu

function el_index {
    cnt=0; for el in "${ar[@]}"; do
        [[ $el == "$1" ]] && echo $cnt && break
        ((++cnt))
    done
}
el_index "Age" # => 1
kopischke
sumber
wow ... saya tidak tahu bahwa tanpa tanda kutip maka itu akan menjadi array. Terima kasih!
G3Y
4
$ export FOO="Name   Age Sex  ID         Address"

Ganti * Usia dengan Usia - ini akan menghapus apa pun sebelum "Usia":

$ echo ${FOO/*Age/Age}
Age Sex ID Address

Dapatkan apa pun sebelum "Usia"

$ echo ${FOO/Age*/}
Name

Dapatkan panjang string itu (yang merupakan indeks "Usia"):

$ BEGIN=${FOO/Age*/}
$ echo ${#BEGIN}
7
pengguna1034081
sumber
Tidak menjawab pertanyaan, tapi wow! Trik licin. Ia bahkan bekerja di abu, dan dengan variabel yang disematkan: export L='debug info warn error'; export GTE='warn'; echo ${L/*${GTE}/${GTE}}mencetak 'warn error'
Steve Tarver
0

Jika Anda tidak harus menggunakan bash secara ketat, tetapi dapat menggunakan program lain yang biasa ditemukan pada sistem dengan bash maka Anda dapat menggunakan sesuatu seperti ini:

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

Python memulai pengindeksan string di nol, oleh karena itu saya menambahkan +1 ke akhir perintah.

jftuga
sumber
0

Anda dapat menggunakan regex asli 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

Keluaran

  2 Name
  9 Age
 13 Sex
 20 ID
 29 Address
Peter.O
sumber
0

Catatan : Dengan asumsi di sini bahwa menurut indeks Anda berarti Anda ingin tahu kata itu (mulai dari 0), bukan karakter mana dalam string kata dimulai. Jawaban lain membahas yang terakhir.

Bukannya aku sadar, tapi kamu bisa membuatnya. Dua trik:

  1. Gunakan kemampuan bawaan untuk membangun untuk membagi input yang tidak dikutip oleh spasi.
  2. Tangani case di mana Anda tidak dapat menemukan kolom yang Anda inginkan. Dalam hal ini, saya memilih untuk mengirim indeks yang ditemukan ke stout dan membiarkan kode status menunjukkan apakah penemuan itu berhasil. Ada kemungkinan lain.

Kode:

#!/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
Owen S.
sumber
0

Coba oneliner javascript berikut dalam shell (gunakan shell javascript):

$ js <<< "x = 'Name   Age Sex  ID         Address'; print(x.indexOf('Age'));"
7

Atau dengan dokumen-sini:

js <<EOF
x = 'Name   Age Sex  ID         Address';
print(x.indexOf('Age'));
EOF
Gilles Quenot
sumber
0

Saya menemukan solusi yang berfungsi dengan baik.

$ string = 'sekarang adalah waktunya'
$ buf = the $ {string # * the}
$ echo $ buf
output: waktu
$ index = $ (($ {# string} - $ {# buf} + 1))
$ gema $ index
output: 8 -> indeks kata pertama "the"

Ia bekerja mirip dengan function indexOf () di Jawa yang mengembalikan kemunculan pertama dari string input.

Temukan solusi ini di sini http://www.linuxquestions.org/questions/linux-newbie-8/bash-string-manipulation-help-670627/ (posting terakhir). Orang ini menyelamatkan hariku. Penghargaan padanya.

Cara lebih cepat jika Anda ingin melakukan substring dari indexof pertama.

$ a = "beberapa string panjang"
$ b = "ri"
$ echo $ {a / * $ b / $ b}
cincin
$ echo $ {a / $ b * / $ b}
beberapa usaha yang panjang

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

Linh Lino
sumber
0

Jika coreutils tersedia, Anda dapat melakukannya dengan cara berikut:

echo $ {str / Age //} | cut -d / -f1 | wc -w

Per permintaan MariusMatutiae saya menambahkan penjelasan bagaimana operasi 3 langkah ini bekerja:

echo $ {str / Age //} 1. ganti string yang sedang dicari karakter unik (dalam kasus saya /)

cut -d / -f1 2. potong seluruh bagian string yang setelah karakter unik

wc -w 3. menghitung dan mencetak kata-kata yang tersisa ini akan memberi kita nomor indeks

Untuk referensi harap periksa:

http://www.tldp.org/LDP/abs/html/parameter-substitution.html (buka: "Perluasan variabel / penggantian substring")
http://www.gnu.org/software/coreutils/manual/coreutils .html (pergi ke: "Perintah cut" dan "doa wc"

PiotrO
sumber
Sementara ini menyelesaikan masalah yang dihadapi, balasan singkat seperti itu disukai di situs-situs ini. Akan lebih bermanfaat jika Anda menghabiskan beberapa kata untuk menjelaskan mengapa ini berhasil. Tolong lakukan itu.
MariusMatutiae
0

Gabungan dari dua jawaban yang diberikan sebelumnya, menggunakan array bash murni dan penggantian substring.

Idenya adalah untuk mendapatkan string dari semua kata sebelum yang Anda inginkan, lalu hitung jumlah kata dalam substring itu dengan membuatnya menjadi array.

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

Tentu saja Umur dapat disimpan dalam variabel lain needle, lalu gunakan ${haystack%$needle*}. Harapkan masalah jika kata yang Anda cari adalah bagian dari kata lain, di mana jawaban kopischke masih berfungsi.

Cimbali
sumber