แยกคำจากสตริงโดยใช้ grep / sed / awk


12

ฉันมีสาย

00:28:04 /usr/lib/jvm/jre/bin/java -DJDBC_CONNECTION_STRING= -Dspring.profiles.active=qa -XX:MaxPermSize=256

และต้องการแยกคำqaที่ตาม-Dspring.profiles.activeมา

ฉันมีบันทึกสตริงในไฟล์ text.txt เพียงเพื่อสาธิตมัน

เมื่อฉันทำ

grep -r -o "spring.profiles.active=" text.txt

ผลที่ได้คือ spring.profiles.active=

คำนี้ไม่เคยเป็นqaมันอาจจะเป็นหรือproddev

สิ่งที่ผมอยากจะทำคือการหาคำspring.profiles.activeและหลังจาก=สารสกัดจากว่าคำว่า

ฉันต้องการเชลล์สคริปต์นี้เพราะฉันใช้คำเพื่อกำหนดค่ารายการอื่น ๆ บนเซิร์ฟเวอร์

เป็นไปได้และถ้าเป็นเช่นนั้นฉันจะทำอย่างไร


ฉันเดาว่ามีการสนทนาเมตาเกี่ยวกับเรื่องนี้อยู่แล้ว แต่คำถามนี้ไม่เฉพาะอูบุนตูโดยสมบูรณ์ ทำไมถึงมาที่นี่แทนที่จะเป็น unix.stackexchange.com ?
Tony Adams

@TonyAdams ใช่แล้วมี: คำถามเกี่ยวกับการประมวลผลข้อความได้รับการกล่าวถึงทางอ้อมที่นี่แล้วอย่างไรก็ตามพวกเขาได้รับการพิจารณาในหัวข้อเสมอและไม่เคยถูกปิด / ย้ายข้อมูล ในอูบุนตู specificness ที่ได้รับการคุ้มครองหลายครั้งเป็นครั้งที่สองเพิ่งนี่และในที่ซ้ำกันและครั้งเดียวที่นี่
kos

คำถามที่ดี! : D
ncomputers

คำตอบ:


20

คุณสามารถใช้grepกับ PCRE ( -P):

grep -Po 'spring.profiles.active=\K[^ ]+' <<<'.....string.....'
  • spring.profiles.active=จะจับคู่สตริงย่อยนี้อย่างแท้จริง\Kจะยกเลิกการจับคู่

  • [^ ]+จะเลือกส่วนที่ต้องการเช่นส่วนหลังspring.profiles.active=จนถึงพื้นที่ถัดไป

สำหรับไฟล์:

grep -Po 'spring.profiles.active=\K[^ ]+' file.txt

ตัวอย่าง:

% grep -Po 'spring.profiles.active=\K[^ ]+' <<<'00:28:04 /usr/lib/jvm/jre/bin/java -DJDBC_CONNECTION_STRING= -Dspring.profiles.active=qa -XX:MaxPermSize=256'
qa

sed จะใช้ตรรกะที่คล้ายกัน:

sed -r 's/.*spring.profiles.active=([^ ]+).*/\1/' <<<'.....string.....'

ตัวอย่าง:

% sed -r 's/.*spring.profiles.active=([^ ]+).*/\1/' <<<'00:28:04 /usr/lib/jvm/jre/bin/java -DJDBC_CONNECTION_STRING= -Dspring.profiles.active=qa -XX:MaxPermSize=256'
qa

การจัดการข้อผิดพลาด:

ในสคริปต์ของคุณคุณอาจต้องการที่จะจัดการกับกรณีที่ไม่มีการแข่งขันในคำอื่น ๆ spring.profiles.active=ที่สายเดิมของคุณไม่ได้มี ในsedตัวอย่างข้างต้นคุณจะได้รับสตริงต้นฉบับทั้งหมดซึ่งอาจสร้างปัญหาได้:

% var="$(sed -r 's/.*spring.profiles.active=([^ ]+).*/\1/' <<<'00:28:04 /usr/lib/jvm/jre/bin/java -DJDBC_CONNECTION_STRING= -XX:MaxPermSize=256')"
% echo $var
00:28:04 /usr/lib/jvm/jre/bin/java -DJDBC_CONNECTION_STRING= -XX:MaxPermSize=256

หากคุณต้องการได้รับสตริงว่างเมื่อไม่มีการจับคู่เพิ่ม-nตัวเลือกให้กับsedคำสั่งและpตัวเลือกในsed sคำสั่งดังนี้:

% var="$(sed -rn 's/.*spring.profiles.active=([^ ]+).*/\1/p' <<<'00:28:04 /usr/lib/jvm/jre/bin/java -DJDBC_CONNECTION_STRING= -XX:MaxPermSize=256')"
% echo $var

% var="$(sed -rn 's/.*spring.profiles.active=([^ ]+).*/\1/p' <<<'00:28:04 /usr/lib/jvm/jre/bin/java -DJDBC_CONNECTION_STRING= -Dspring.profiles.active=qa -XX:MaxPermSize=256')"
% echo $var
qa

จากนั้นคุณสามารถทดสอบว่า $ var ว่างเปล่าหรือไม่


ขอบคุณ @ heemay ทำงานได้สมบูรณ์แบบ ตอนนี้ฉันแค่ต้องสคริปต์ที่ ฉันจะทำเครื่องหมายตามคำตอบ
Gman

@heemay คุณจะรู้ว่าฉันสามารถสคริปต์นี้ ฉันมีมันในสคริปต์และเมื่อมันทำงานมันกลับมา qa ฉันต้องการบันทึกผลลัพธ์ในตัวแปรที่เรียกว่า env แล้วเปรียบเทียบกับสิ่งที่ต้องการ หาก [env == qa]; ถ้างั้น // ทำอะไร
ซัก

1
@Gman ใช่ .. เพียงแค่ใช้การทดแทนคำสั่ง: var="$(grep -Po 'spring.profiles.active=\K[^ ]+' file.txt)"แทนที่file.txtด้วย<<<'...string...'ถ้าใส่เป็นสตริงไม่ใช่ไฟล์ .. จากนั้นคุณสามารถทำได้if [ "$var" = 'qa' ]; then do something; else do something; fi
heemayl

1

การใช้ awk

awk -F"-Dspring.profiles.active=" '{sub(/ .*/,"",$2);print $2}' <<<'your_string'

หรือ

awk -F"-Dspring.profiles.active=" '{sub(/ .*/,"",$2);print $2}' your_file

ตัวอย่าง

% awk -F"-Dspring.profiles.active=" '{sub(/ .*/,"",$2);print $2}' <<<'00:28:04 /usr/lib/jvm/jre/bin/java -DJDBC_CONNECTION_STRING= -Dspring.profiles.active=qa -XX:MaxPermSize=256'
qa

1

ฉันจะโยน Perl หนึ่งในการผสม:

<<<'string' perl -lane '$F[3]=~s/.*?=//;print($F[3])'
  • -l: เปิดใช้งานการประมวลผลโดยอัตโนมัติ มันมีเอฟเฟกต์สองอย่างแยกกัน ก่อนอื่นมันจะ chomps $ / (ตัวคั่นเร็กคอร์ดอินพุต) โดยอัตโนมัติเมื่อใช้กับ -n หรือ -p ประการที่สองมันกำหนด $ \ (ตัวคั่นเร็กคอร์ดเอาท์พุท) ให้มีค่าของ octnum เพื่อให้คำสั่งการพิมพ์ใด ๆ ที่จะมีตัวคั่นนั้นเพิ่มกลับมา หากไม่ระบุ octnum ให้ตั้งค่า $ \ เป็นค่าปัจจุบันของ $ /
  • -a: เปิดโหมด autosplit เมื่อใช้กับ -n หรือ -p คำสั่ง split โดยปริยายไปยังอาร์เรย์ @F นั้นทำขึ้นเป็นสิ่งแรกภายใน implicit ขณะที่ loop สร้างโดย -n หรือ -p
  • n: ทำให้ Perl ถือว่าวนรอบต่อไปนี้รอบโปรแกรมของคุณ, ซึ่งทำให้วนซ้ำอาร์กิวเมนต์ของชื่อไฟล์ค่อนข้างจะเหมือนกับ sed -n หรือ awk:

    LINE:
      while (<>) {
          ...             # your program goes here
      }
  • -e: อาจใช้เพื่อป้อนโปรแกรมหนึ่งบรรทัด
% <<<'00:28:04 /usr/lib/jvm/jre/bin/java -DJDBC_CONNECTION_STRING= -Dspring.profiles.active=qa -XX:MaxPermSize=256' perl -lane '$F[3]=~s/.*?=//;print($F[3])'
qa

regex เดิมสามารถใช้ได้เช่นนี้:perl -nle '/spring.profiles.active=\K([^ ]+)/ && print $1' <<<'00:28:04 /usr/lib/jvm/jre/bin/java -DJDBC_CONNECTION_STRING= -Dspring.profiles.active=qa -XX:MaxPermSize=256'
Manwe
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.