วิธีการหาดัชนีของคำในสตริงในทุบตี?


10

ในสคริปต์ทุบตี

ฉันมีสตริงที่มีหลายคำคั่นด้วยช่องว่างหนึ่งหรือมากกว่าหนึ่งช่องว่าง เช่น:

Name   Age Sex  ID         Address

หากฉันต้องการค้นหาคำใด ๆ ตัวอย่างเช่นฉันต้องการค้นหาดัชนีของคำว่า "อายุ" ฉันจะทำอย่างไร

มีคำสั่งใดบ้างที่จะส่งคืนหมายเลขดัชนีของคำที่ฉันต้องการโดยตรงหรือไม่?

ขอบคุณ


วิธีการแก้ปัญหาจะต้องมีการทุบตีอย่างเคร่งครัด? หรือสามารถใช้ awk, grep และอื่น ๆ ได้?
jftuga

โพสต์ที่เกี่ยวข้อง: วิธีการพิมพ์คอลัมน์บางชื่อ?
zx8754

คำตอบ:


12

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"

แทนที่ * อายุพร้อมอายุ - สิ่งนี้จะลบอะไรก่อน "อายุ":

$ 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}}พิมพ์ 'เตือนข้อผิดพลาด'
Steve Tarver

0

หากคุณไม่ต้องใช้ bash อย่างเคร่งครัด แต่สามารถใช้โปรแกรมอื่น ๆ ที่พบได้ทั่วไปในระบบที่มี bash คุณสามารถใช้สิ่งต่อไปนี้:

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

Python เริ่มต้นมันคือการสร้างดัชนีสตริงที่ศูนย์ดังนั้นฉันจึงเพิ่ม +1 ที่ส่วนท้ายของคำสั่ง


0

คุณสามารถใช้ regex ดั้งเดิมของ 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. ใช้ความสามารถมา แต่กำเนิดของสำหรับสร้างขึ้นเพื่อแยกการป้อนข้อมูล unquoted โดยช่องว่าง
  2. จัดการกรณีและปัญหาที่คุณไม่สามารถหาคอลัมน์ที่คุณต้องการ ในกรณีนี้ฉันเลือกที่จะส่งดัชนีที่ค้นพบไปยังอ้วนและให้รหัสสถานะระบุว่าการค้นหานั้นประสบความสำเร็จหรือไม่ มีความเป็นไปได้อื่น ๆ

รหัส:

#!/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 ต่อไปนี้ในเชลล์ (ใช้เชลล์จาวาสคริปต์):

$ 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}
แหวน
$ echo $ {a / $ b * / $ b}
บางส่วนยาว

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


0

หาก coreutils พร้อมใช้งานคุณสามารถทำได้ด้วยวิธีต่อไปนี้:

echo $ {str / Age //} | ตัด -d / -f1 | ห้องสุขา

คำขอ MariusMatutiae ต่อฉันกำลังเพิ่มคำอธิบายวิธีการทำงานของ 3 ขั้นตอนนี้:

echo $ {str / Age //} 1. แทนที่ string ซึ่งกำลังค้นหา char ที่ไม่ซ้ำกัน (ในกรณีของฉัน /)

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

การผสมกันของสองคำตอบที่ได้รับก่อนหน้านี้โดยใช้อาร์เรย์ทุบตีบริสุทธิ์และการเปลี่ยนสตริงย่อย

แนวคิดคือการได้รับสตริงของทุกคำก่อนคำที่คุณต้องการจากนั้นนับจำนวนคำในสตริงย่อยนั้นโดยทำให้เป็นอาร์เรย์

$ 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*}คาดหวังปัญหาหากคำที่คุณค้นหาเป็นส่วนย่อยของคำอื่นซึ่งในกรณีนี้คำตอบของ kopischke ยังคงทำงานอยู่


0

นี่เป็นคำถามอายุ 7 ปี แต่บางคนอาจต้องการคำตอบในการทุบตีบริสุทธิ์

STRING="Name   Age Sex  ID         Address"
INDEXOF_AGE=${#${STRING/Age*/}}
echo $INDEXOF_AGE
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.