Bash scripting - làm thế nào để nối các chuỗi sau đây?


8

Đây là một phần của bashkịch bản cpuidkhám phá trong 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`

Vì vậy, đối với máy tính xách tay của tôi, phần kịch bản này (hiển thị ở đây) cho 60.

Bây giờ làm thế nào để làm điều này bằng cách sử dụng các biến cục bộ CHỈ, không có tệp trung gian ( cpu.txt) liên quan?

Câu trả lời:


10

Chỉ trong một bước:

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

Các đòn bẩy trên thay thế quá trình thay thế ( <()) và thay thế lệnh ( $()).

  • Hai thay thế lệnh được thay thế bằng STDOUT của các lệnh bên trong

  • cpuidlệnh được đưa vào thay thế quá trình, STDOUT sẽ được trả về dưới dạng mô tả tệp, grepsẽ thực hiện khớp phù hợp cần thiết trên nó, chúng tôi đã sử dụng grepvới PCRE ( -P) để chỉ lấy ( -o) phần mong muốn và -m1sẽ dừng sau lần khớp đầu tiên để tránh lặp lại

  • printf được sử dụng để có được đầu ra ở định dạng mong muốn

Thí dụ:

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

9

Bạn có thể tránh tệp trung gian bằng cách sử dụng đường ống và bạn có thể tránh sử dụng cả hai sedawkbằng cách thực hiện khớp và thay thế trong awkví dụ:

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

1

Không đưa ra các giả định và thay đổi bản chất của mẫu, đây là sự thay thế giảm lưu trữ đầu ra trong một biến theo yêu cầu:

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 } ')

Dòng đầu tiên đặt biến CPUIDthành đầu ra của /usr/bin/cpuid
I sau đó đặt biến alà đầu ra ( echo) của CPUIDbiến được đặt trong dòng trên (điều này sau đó được dẫn đến các lệnh được cung cấp của bạn).


1
Cám ơn vì đã giải thích. Đây là gần nhất với mức độ hiểu biết của tôi. Thật không may, tôi không phải là chuyên gia về sed, awk và perl, nhưng một số hiểu biết ban đầu tôi có. :-)
không ai là

1
Dòng catđầu tiên không nên ở đó. Nó khiến CPUID được gán nội dung của tệp thực thi nhị phân thay vì đầu ra của nó.
Joe

0

quyến rũ

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

Khi tôi có 8 lõi, máy tính của tôi phát ra:

50  
50  
50  
50  
50  
50  
50  
50  

tac đảo ngược thứ tự các dòng từ cpuid để tôi có thể sử dụng ^ CPU làm đầu cuối của bản ghi CPU, một mô hình cũng được mở rộng và họ mở rộng sau đó xảy ra theo đúng thứ tự


0

Điều này không tối ưu hóa các lệnh ban đầu của bạn, nhưng dấu chấm phẩy cho phép bạn đặt 2 lệnh lại với nhau để tránh hoàn toàn thao tác nối:

foo="$(firstcommand; secondcommand)"

Hoặc, cụ thể cho tình huống của bạn:

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

Nếu bạn quan tâm đến các dòng mới, bạn sẽ muốn đặt dấu ngoặc kép trước chữ cái đầu $(và sau khi đóng)


0

Đây là một cách để làm điều đó awk(toàn bộ đầu ra được thực hiện bởi mã trong câu trả lời của bạn).

Khi bạn kết thúc việc xử lý lại cùng một đầu vào lặp đi lặp lại, điều đó thường chỉ ra rằng cách tiếp cận khác có thể tốt hơn.

awklà hoàn hảo để xử lý văn bản đầu vào như thế này. awkcác chương trình dài hơn rất nhiều so với những thứ được thực hiện sed, nhưng chúng dễ đọc hơn nhiều và bạn có thể thêm các câu lệnh in vào chúng để làm cho việc gỡ lỗi dễ dàng hơn nhiều .

Tôi để lại các tuyên bố gỡ lỗi của tôi trong (nhận xét ra). Bạn có thể bỏ qua chúng để xem kịch bản hoạt động như thế nào.

Bạn phải đặt awkchương trình ở một nơi nào đó và nơi dễ nhất trong một trường hợp sử dụng như thế này là đặt toàn bộ trong một chuỗi trích dẫn trên awkdòng lệnh.

Bằng cách này, bạn không phải lưu trữ nó trong một tệp riêng biệt hoặc trong một tệp tạm thời, do đó không có quản lý tệp liên quan và tập lệnh sẽ tự đứng.

Chương trình này có vẻ dài, nhưng hầu như tất cả các bình luận, tuyên bố gỡ lỗi và khoảng trắng.

#!/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

Cho đến nay, tôi đang đọc tất cả các ý kiến, và tôi sẽ cố gắng sử dụng tất cả chúng. Như tôi đã viết cho NGRhodes: "thật không may, tôi không phải là chuyên gia về sed, awk và perl, nhưng một số hiểu biết ban đầu tôi có.

Rất cám ơn tất cả những người đã làm / trình bày những ví dụ tuyệt vời này. Tôi chân thành hy vọng nhiều người sẽ đọc những dòng này và đào sâu các kỹ năng viết kịch bản của họ!

Trên thực tế, tôi đã làm một số loại cocktail về những gì tất cả các bạn gợi ý cho tôi:

/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

Kết quả là: 40651 0004-0651-0000-0000-0000-0000 đó là những gì tôi mong đợi! :-)


Nếu bạn định làm tất cả những điều đó và sử dụng awk, thì sẽ tốt hơn nếu viết lại toàn bộ như một chương trình awk nhỏ. Ngoài ra, hãy xem nhận xét của tôi để @NGRhodes trả lời về lý do tại sao dòng đầu tiên đó không hoạt động.
Joe
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.