Bash scripting - วิธีเชื่อมสตริงต่อไปนี้?


8

นี่เป็นส่วนหนึ่งของbashสคริปต์ที่ทำการcpuidค้นพบใน Linux (Ubuntu / Fedora):

/usr/bin/cpuid > id.txt    
CPUID=id.txt    
echo `grep "extended model" $CPUID` | sed 's/0x//' | awk ' { print $4 } ' > cpu.txt    
a=`cat cpu.txt`    
echo `grep "extended family" $CPUID`| sed 's/0x//' | awk ' { print $4 } ' > cpu.txt    
a+=`cat cpu.txt`

ดังนั้นสำหรับแล็ปท็อปของฉันส่วนนี้ของสคริปต์ (แสดงที่นี่) ให้ 60

ตอนนี้วิธีการทำเช่นนี้โดยใช้ตัวแปรท้องถิ่นเท่านั้นไม่ได้มีไฟล์ระดับกลาง ( cpu.txt) ที่เกี่ยวข้อง?

คำตอบ:


10

ในครั้งเดียว:

printf '%s%s\n' "$(grep -Pom1 'extended model.*\(\K\d+' <(cpuid))" \
                "$(grep -Pom1 'extended family.*\(\K\d+' <(cpuid))"

การใช้ประโยชน์จากการทดแทนกระบวนการด้านบน ( <()) และการทดแทนคำสั่ง ( $())

  • การแทนที่คำสั่งสองรายการจะถูกแทนที่ด้วย STDOUT ของคำสั่งภายใน

  • cpuidคำสั่งใส่ในการทดแทนกระบวนการ STDOUT จะถูกส่งกลับเป็นไฟล์อธิบายgrepจะทำการจับคู่ที่จำเป็นกับมันเราได้ใช้grepกับ PCRE ( -P) เพื่อรับเฉพาะ ( -o) ส่วนที่ต้องการและ-m1จะหยุดหลังจากการแข่งขันครั้งแรกเพื่อหลีกเลี่ยงการซ้ำ

  • printf ใช้เพื่อรับเอาต์พุตในรูปแบบที่ต้องการ

ตัวอย่าง:

$ printf '%s%s\n' "$(grep -Pom1 'extended model.*\(\K\d+' <(cpuid))" "$(grep -Pom1 'extended family.*\(\K\d+' <(cpuid))"
30

9

คุณสามารถหลีกเลี่ยงไฟล์ระดับกลางได้โดยใช้ไพพ์และคุณสามารถหลีกเลี่ยงการใช้ทั้งsedและawkโดยการจับคู่และทดแทนในawkเช่น

/usr/bin/cpuid | 
  awk '/extended model/ {mod = substr($4,3)} /extended family/ {fam = substr($4,3)} 
  END {printf "%d%d\n", mod, fam}'

1

โดยไม่ต้องทำการตั้งสมมุติฐานและเปลี่ยนแปลงลักษณะของตัวอย่างนี่คือการแทนที่ที่เก็บเอาต์พุตในตัวแปรตามที่ร้องขอ:

CPUID=$(/usr/bin/cpuid)
a=$(echo "$CPUID" | grep 'extended model' | sed 's/0x//' | awk ' { print $4 } ')
a+=$(echo "$CPUID" | grep 'extended family' | sed 's/0x//' | awk ' { print $4 } ')

บรรทัดแรกตั้งค่าตัวแปรCPUIDเป็นเอาต์พุตของ/usr/bin/cpuid
I จากนั้นตั้งค่าตัวแปรaเป็นเอาต์พุต ( echo) ของCPUIDชุดตัวแปรในบรรทัดด้านบน (จากนั้นจะถูกไพพ์ตามคำสั่งที่คุณให้


1
ขอบคุณสำหรับคำอธิบาย อันนี้ใกล้เคียงกับระดับความเข้าใจของฉันมากที่สุด น่าเสียดายที่ฉันไม่ใช่ผู้เชี่ยวชาญที่จะล่อลวง awk และ perl แต่มีความเข้าใจเบื้องต้นที่ฉันมี :-)
ไม่มีใคร

1
catในบรรทัดแรกไม่ควรจะมี ทำให้ CPUID ได้รับมอบหมายเนื้อหาของไบนารีที่ปฏิบัติการได้มากกว่าเอาท์พุท
โจ

0

sed

cpuid | tac | sed '/^CPU/{s/.*//;x;s/\n//g;p;d};/extended \(model\|family\)/!d;s/.*(\(.*\)).*/\1/;H;d'

เนื่องจากฉันมี 8 คอร์พีซีของฉันจึงปล่อย:

50  
50  
50  
50  
50  
50  
50  
50  

tac ฝืนคำสั่งของบรรทัดจาก cpuid เพื่อให้ฉันสามารถใช้ ^ CPU เป็นเทอร์มินอลของเร็กคอร์ด CPU, โมเดลเพิ่มเติมและตระกูลขยายนั้นเกิดขึ้นในลำดับที่ถูกต้อง


0

สิ่งนี้ไม่ได้เพิ่มประสิทธิภาพคำสั่งเริ่มต้นของคุณ แต่เซมิโคลอนช่วยให้คุณสามารถรวม 2 คำสั่งเข้าด้วยกันเพื่อหลีกเลี่ยงการดำเนินการต่อข้อมูลทั้งหมด:

foo="$(firstcommand; secondcommand)"

หรือเฉพาะสถานการณ์ของคุณ:

a=$(grep "extended model" $CPUID | sed 's/0x//' | awk ' { print $4 };
grep "extended family" $CPUID | sed 's/0x//' | awk ' { print $4 };)

หากคุณสนใจเกี่ยวกับการขึ้นบรรทัดใหม่คุณจะต้องใส่เครื่องหมายคำพูดคู่ก่อนเริ่มต้น$(และหลังการปิด)


0

นี่คือวิธีที่จะทำในawk(ผลลัพธ์ทั้งหมดตามที่ทำโดยรหัสในคำตอบของคุณ)

เมื่อคุณจบการประมวลผลอินพุตเดียวกันซ้ำแล้วซ้ำอีกมักจะบ่งชี้ว่าวิธีอื่นอาจดีกว่า

awkเหมาะสำหรับการประมวลผลการป้อนข้อความแบบนี้ awkโปรแกรมที่มีมากเกินกว่าสิ่งที่ทำมีsedแต่พวกเขามีมากง่ายต่อการอ่านและคุณสามารถเพิ่มงบการพิมพ์ให้กับพวกเขาที่จะทำให้การแก้จุดบกพร่องมากได้ง่ายขึ้น

ฉันออกจากการแก้ไขข้อบกพร่องใน (ความเห็น) คุณสามารถยกเลิกการใส่เครื่องหมายข้อคิดเห็นเพื่อดูว่าสคริปต์ทำงานอย่างไร

คุณต้องวางawkโปรแกรมไว้ที่ใดที่หนึ่งและสถานที่ที่ง่ายที่สุดในกรณีการใช้งานเพียงครั้งเดียวเช่นนี้คือการใส่ข้อมูลทั้งหมดลงในสตริงที่ยกมาเดี่ยวบนawkบรรทัดคำสั่ง

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

โปรแกรมนี้ดูยาว แต่มันเป็นความคิดเห็นเกือบทั้งหมดการแก้ไขข้อผิดพลาดและพื้นที่สีขาว

#!/bin/bash

## Whole awk program is one single quoted string
## on the awk command line
## so we don't need to put it in a separate file 
## and so bash doesn't expand any of it
## Debugging statements were left in, but commented out

/usr/bin/cpuid | awk '
BEGIN {  ## initialize variables - probably unnecessary
  em = ""
  ef = ""
  fa = ""
  mo = ""
  si = ""
  ps = ""
}

## get each value only once

## extended model is in field 4 starting at the third character
## of a line which contains "extended model"
/extended model/ && em == "" {
  em = substr($4, 3)
  ##print "EM " em
}

## extended family is in field 4 starting at the third character
## of a line which contains "extended family"
/extended family/ && ef == "" {
  ef = substr($4, 3)
  ##print "EF " ef
}

## family is in the last field, starting at the second character
## and is two characters shorter than the field "()"
## of a line which starts with "family"
## (so it does not match "extended family")
$1 == "family" && fa == "" {
  ##print NF " [" $NF "]"
  ##print "[" substr($NF, 2) "]"
  l = length($NF) - 2
  fa = substr($NF, 2, l)
  ##print "FA " fa
}

## model is in the third field, starting at the third character
## of a line which starts with "model"
## (so it does not match "extended model")
$1 == "model" && mo == "" {
  mo = substr($3, 3)
  ##print "MO " mo
}


## stepping id is in field 4 starting at the third character
## of a line which contains "stepping id"
/stepping id/ && si == "" {
  si = substr($4, 3)
  ##print "SI " si
}

## processor serial number is in field 4 starting at the third character
## of a line which contains "processor serial number:"
/processor serial number:/ && ps == "" {
  ps = $4
  ##print "PS " ps
}

## Quit when we have all the values we need
em != "" && ef != "" && fa != "" && mo != "" && si != "" && ps != "" {
  exit
}

END {
  print em ef fa mo si " " ps
}
'

0

จนถึงตอนนี้ฉันกำลังอ่านความคิดเห็นทั้งหมดและฉันจะพยายามใช้พวกเขาทั้งหมด ตามที่ฉันเขียนถึง NGRhodes: "โชคไม่ดีที่ฉันไม่ชำนาญที่จะล่อลวง awk และ perl แต่มีความเข้าใจเบื้องต้นที่ฉันมี

ขอบคุณมากสำหรับทุกคนที่ได้ / นำเสนอตัวอย่างที่ยอดเยี่ยมเหล่านี้ ฉันหวังเป็นอย่างยิ่งว่าผู้คนจำนวนมากจะอ่านบรรทัดเหล่านี้และพัฒนาทักษะการเขียนสคริปต์ให้ลึกซึ้งยิ่งขึ้น!

ที่จริงฉันทำค็อกเทลที่คุณแนะนำให้ฉัน:

/usr/bin/cpuid > id.txt  ***[CPUID=$(cat /usr/bin/cpuid) does not work for me]***  
CPUID=id.txt  
a=$(echo `cat $CPUID | grep -m1 'extended model' | sed 's/0x//' | awk ' { print $4 } '`)  
a+=$(echo `cat $CPUID | grep -m1 'extended family' | sed 's/0x//' | awk ' { print $4 } '`)  
a+=$(echo `cat $CPUID | grep -m1 'AMD' | sed 's/(//' | sed 's/)//' | awk ' { print $13 } '`)  
a+=$(echo `cat $CPUID | grep -m1 'model' | sed 's/0x//' | awk ' { print $3 } '`)  
a+=$(echo `cat $CPUID | grep -m1 'stepping id' | sed 's/0x//' | awk ' { print $4 } '`)  
a+=' '  
a+=$(echo `cat $CPUID | grep -m1 'processor serial number:' | awk ' { print $4 } '`)  
echo $a

ผลลัพธ์คือ: 40651 0004-0651-0000-0000-0000-0000ซึ่งเป็นสิ่งที่ฉันคาดหวัง! :-)


หากคุณกำลังจะทำสิ่งนั้นทั้งหมดและใช้ awk ต่อไปจะเป็นการดีกว่าถ้าคุณเขียนโปรแกรมใหม่ทั้งหมดเป็นโปรแกรม awk ขนาดเล็ก นอกจากนี้โปรดดูความคิดเห็นของฉันที่ @NGRhodes ตอบว่าทำไมบรรทัดแรกไม่ทำงาน
Joe
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.