วิธีแยกคู่ค่าคีย์จากคำสั่ง ps


10

ฉันพยายามดึงชื่อแอปพลิเคชันจากpsคำสั่งเช่นนี้:

ps -af -u sas |grep "java"| grep -v "grep"

และจะสร้างสิ่งต่อไปนี้:

sas 24431     1  0 Oct10 ?        00:51:08 /usr/lib/jvm/java-1.7.0-oracle-1.7.0.25.x86_64/jre/bin/java -Denv=DEV -Dapp.name=myApp -Xms512m -Xmx1g -Dlog.dir=/apps/java/logs

ฉันพยายามใช้egrepแต่ดูเหมือนจะไม่ทำงาน:

ps -af -u sas|grep "java"| grep -v "grep"| egrep -o "-Dapp.name"

ฉันจะได้รับเฉพาะ-Dapp.nameค่า "myApp" ได้อย่างไร


หากgrepรูปแบบเริ่มต้นด้วย-คุณจะต้องวางไว้หลัง-eตัวเลือก มิฉะนั้นจะถือว่าเป็นตัวเลือก แต่นั่นจะตรงกับคำ-Dapp.nameไม่ใช่ส่วนหลังจากนั้น
Barmar

ผลัดกัน:grep -o -- -Dapp.name
strugee

คุณสามารถใช้grep [j]avaเพื่อหลีกเลี่ยงคำสั่งgrep -v "grep"(ทดสอบกับ bash)
HVNSweeting

คำตอบ:



8

คุณไม่ได้แสดงข้อความข้อผิดพลาดที่คุณได้รับ แต่อาจเป็นไปได้

grep: วิธีการของอุปกรณ์ที่ไม่รู้จัก

นั่นเป็นเพราะเช่นเดียวกับโปรแกรมบรรทัดคำสั่งอื่น ๆ หรืออย่างน้อยที่สุดgrepสมมติว่าสิ่งใดก็ตามที่เริ่มต้นด้วย a -เป็นตัวเลือกและพยายามแยกวิเคราะห์เช่นนี้ ในกรณี-Dนี้ใช้เพื่อแนะนำgrepวิธีจัดการกับไฟล์อุปกรณ์ (ดูman grepรายละเอียด) วิธีหนึ่งในการหลีกเลี่ยงปัญหานี้คือการใช้--ซึ่งบอกgrepว่าสิ่งต่อไปนี้ไม่ใช่ตัวเลือกการตั้งค่าสถานะ

เมื่อรวมเข้ากับความสามารถ PCRE ของ GNU grepคุณสามารถ:

ps -af -u sas | grep -v grep | grep -Po -- '*-\KDapp.name=[^\s]+'

นิพจน์ทั่วไปค้นหา-และละทิ้งมัน ( \K) จากนั้นสตริงDapp.name=ตามด้วยอักขระที่ไม่ใช่ช่องว่างให้มากที่สุด ผลลัพธ์คือ:

Dapp.name=myApp

หากคุณต้องการให้myAppส่วนที่บันทึกไว้ในตัวแปรฉันจะค้นหาเพียงอย่างเดียว:

ps -af -u sas | grep -v grep | grep -Po -- '-Dapp.name=\K[^\s]+'

ในการกำหนดให้กับตัวแปร:

$ app="$(ps -af -u sas | grep -v grep | grep -Po -- '-Dapp.name=\K[^\s]+')"
$ echo $app
myApp

อย่างไรก็ตามคุณไม่ควรgrepนำเอาท์พุทของpsสิ่งpgrepนี้มาใช้เพื่อ:

app="$(pgrep -a java | grep -Po -- '^Dapp.name=\K[^\s]+')"


3

เมื่อใดก็ตามที่คุณใช้ps … | grep …และจำเป็นต้องยกเว้น grep ออกจากผลลัพธ์แสดงว่าคุณทำผิด

กฎการแยกวิเคราะห์เอาต์พุตของ zeroth psคือการใช้เครื่องมือที่เชื่อถือได้มากขึ้นเช่นpgrepถ้ามี ถ้าคุณมี pgrep แล้วแสดงรายการกระบวนการทั้งหมดใช้คำสั่งpgrep -f java javaตัวเลือก-lเพิ่มบรรทัดคำสั่งสำหรับแต่ละกระบวนการ

เพื่อแยกอาร์กิวเมนต์ไปที่-Dapp.nameคุณสามารถใช้ sed จับคู่ทั้งบรรทัดจัดเรียงสิ่งที่น่าสนใจในกลุ่มและพิมพ์กลุ่มนั้น

pgrep -lf java | sed -n 's/^.*-Dapp\.name=\([^ ]*\).*$/\1/p'

กฎข้อแรกของการแยกวิเคราะห์ผลลัพธ์ของpsคือการใช้ตัวเลือก-oเพื่อเลือกเขตข้อมูลที่คุณต้องการ ที่นี่คุณสนใจเฉพาะอาร์กิวเมนต์คำสั่งเท่านั้นดังนั้นพิมพ์เฉพาะ

ps -e -o args= | sed -n 's/^.*-Dapp\.name=\([^ ]*\).*$/\1/p'

3

ซับซ้อนกว่าคำตอบอื่น ๆ แต่สิ่งนี้ใช้getoptเพื่อจัดการการแยกวิเคราะห์สำหรับคุณ อีกทางเลือกหนึ่ง

getopt -aql 'Dapp.name:' $(\
    ps -af -u sas | grep java | grep -v grep | tr -s ' ' | cut -d' ' -f8-\
) | cut -d"'" -f2
  1. คำสั่งของคุณ: ps -af -u sas | grep java | grep -v grep
  2. tr -s ' ' "บีบ" ช่องว่างหลาย ๆ ช่องลงในช่องว่างเดียวในการเตรียมการ cut
  3. cut -d' ' -f8- แยกบรรทัดด้วยช่องว่างและคว้าฟิลด์ทั้งหมดหลังจากรวม 8 รายการผลลัพธ์คือ /usr/lib/jvm/java-1.7.0-oracle-1.7.0.25.x86_64/jre/bin/java -Denv=DEV -Dapp.name=myApp -Xms512m -Xmx1g -Dlog.dir=/apps/java/logs
  4. getopts -aql 'Dapp.name:' $(...)แยกวิเคราะห์ตัวเลือกคำสั่งและส่งออกเฉพาะชื่อยาวที่ตรงกับDapp.nameผู้ที่มีค่า (แสดงโดย:) ผลคือ--Dapp.name 'myApp' --
  5. cut -d"'" -f2 คว้าสิ่งของในเครื่องหมายคำพูดเดี่ยว
  6. ผลลัพธ์คือ: myApp

0

ฉันจะใช้pgrepแทนpsเช่น:

$ pgrep -fa java | grep -op "(<=-Dapp.name=)\w+"

สิ่งนี้จะส่งกลับกระบวนการทั้งหมดที่จับคู่javaแล้วกรองออกเป็นการแสดงเฉพาะกระบวนการที่มี-Dapp.name=อยู่ บิตสุดท้าย\w+จะแสดงชื่อโปรแกรมโดยสมมติว่าไม่มีช่องว่าง

หมายเหตุ:-Pสลับไปgrepขอความสามารถในการระบุสิ่งที่ใช้PCRE - นิพจน์ปกติ ไม่ใช่ทุกรุ่นที่grepรองรับ แต่ส่วนใหญ่จะมาพร้อมกับ Linux ที่ทันสมัยกว่า

หากคุณต้องการเอาต์พุตคีย์ / ค่าทั้งหมดให้เปลี่ยนสิ่งต่อไปนี้:

$ pgrep -fa java | grep -oP -- "-Dapp.name=\w+"
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.