Bash scripting - bagaimana menggabungkan string berikut?

8

Inilah bagian bashskrip yang melakukan cpuidpenemuan di 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`

Jadi, untuk laptop saya, bagian skrip ini (ditunjukkan di sini) memberikan 60.

Sekarang bagaimana melakukan ini menggunakan HANYA variabel lokal, tidak cpu.txtmelibatkan file perantara ( )?

tak seorangpun
sumber

Jawaban:

10

Dalam satu pergi:

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

Pengungkitan proses leverage di atas ( <()), dan substitusi perintah ( $()).

  • Dua pergantian perintah diganti dengan STDOUT dari perintah di dalamnya

  • cpuidperintah dimasukkan ke dalam proses substitusi, STDOUT akan dikembalikan sebagai deskriptor file, grepakan melakukan pencocokan yang diperlukan di atasnya, kami telah menggunakan grepPCRE ( -P) untuk mendapatkan hanya ( -o) bagian yang diinginkan, dan -m1akan berhenti setelah pertandingan pertama untuk menghindari pengulangan

  • printf digunakan untuk mendapatkan output dalam format yang diinginkan

Contoh:

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

Anda dapat menghindari file perantara dengan menggunakan pipa , dan Anda dapat menghindari menggunakan keduanya seddan awkdengan melakukan pencocokan dan substitusi dalam awkmis

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

Tanpa membuat asumsi dan mengubah sifat sampel, berikut adalah setetes penggantian yang menyimpan output dalam variabel seperti yang diminta:

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

Baris pertama mengatur variabel CPUIDke output /usr/bin/cpuid
I kemudian mengatur variabel amenjadi output ( echo) dari CPUIDvariabel yang diatur dalam baris di atas (ini kemudian disalurkan ke perintah yang Anda berikan).

NGRode
sumber
1
Terima kasih atas penjelasannya. Yang ini paling dekat dengan tingkat pemahaman saya. Sayangnya, saya bukan ahli sed, awk dan perl, tetapi beberapa pemahaman awal yang saya miliki. :-)
tidak ada orang
1
Baris catpertama tidak seharusnya ada di sana. Itu menyebabkan CPUID untuk ditugaskan isi biner dieksekusi daripada outputnya.
Joe
0

sed

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

karena saya memiliki 8 core, pc saya memancarkan:

50  
50  
50  
50  
50  
50  
50  
50  

tac membalik urutan baris dari cpuid sehingga saya dapat menggunakan ^ CPU sebagai terminator dari catatan CPU, model yang juga diperluas dan keluarga besar kemudian terjadi dalam urutan yang benar

Sam Liddicott
sumber
0

Ini tidak mengoptimalkan perintah awal Anda, tetapi titik koma memungkinkan Anda untuk menempatkan 2 perintah bersama-sama untuk menghindari operasi penggabungan sepenuhnya:

foo="$(firstcommand; secondcommand)"

Atau, spesifik untuk situasi Anda:

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

Jika Anda peduli dengan baris baru, Anda ingin memberi tanda kutip ganda sebelum inisial $(dan setelah penutupan)

Peter Bowers
sumber
0

Inilah cara untuk melakukannya awk (seluruh output seperti yang dilakukan oleh kode dalam jawaban Anda).

Ketika Anda akhirnya memproses ulang input yang sama berulang kali, biasanya menunjukkan bahwa pendekatan lain mungkin lebih baik.

awksangat cocok untuk memproses input teks seperti ini. awkprogram jauh lebih lama daripada yang dilakukan dengan sed, tetapi mereka jauh lebih mudah dibaca dan Anda dapat menambahkan pernyataan cetak untuk membuatnya lebih mudah debugging .

Saya meninggalkan pernyataan debugging saya di (berkomentar). Anda dapat menghapus tanda komentar mereka untuk menonton bagaimana skrip bekerja.

Anda harus meletakkan awkprogram di suatu tempat dan tempat termudah dalam kasus penggunaan tunggal seperti ini adalah untuk meletakkan semuanya dalam satu string yang dikutip pada awkbaris perintah.

Dengan cara ini Anda tidak perlu menyimpannya dalam file terpisah atau dalam file sementara, jadi tidak ada manajemen file yang terlibat dan skrip akan berdiri sendiri.

Program ini terlihat panjang, tetapi hampir semua komentar, pernyataan debugging, dan spasi.

#!/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
}
'
Joe
sumber
0

Sejauh ini, saya membaca semua komentar, dan saya akan mencoba menggunakan semuanya. Seperti yang saya tulis ke NGRhodes: "sayangnya, saya tidak ahli untuk sed, awk dan perl, tetapi beberapa pemahaman awal yang saya miliki.

Banyak terima kasih kepada semua yang melakukan / mempresentasikan contoh-contoh luar biasa ini. Saya sungguh berharap lebih banyak orang akan membaca baris-baris ini dan memperdalam keterampilan menulis mereka!

Sebenarnya, saya melakukan beberapa koktail dari apa yang Anda semua menyarankan kepada saya:

/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

Hasilnya adalah: 40651 0004-0651-0000-0000-0000-0000 yang saya harapkan! :-)

tidak ada
sumber
Jika Anda akan melakukan semua itu dan menggunakan awk, akan lebih bersih untuk menulis ulang semuanya sebagai program awk kecil. Juga, lihat komentar saya untuk jawaban @NGRhodes mengapa baris pertama itu tidak berfungsi.
Joe