Bash-Scripting - wie verkette ich die folgenden Zeichenfolgen?

8

Hier ist der Teil des bashSkripts, cpuidder unter Linux (Ubuntu / Fedora) entdeckt wird:

/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`

Für meinen Laptop ergibt dieser Teil des Skripts (hier gezeigt) 60.

Wie geht das nun mit NUR lokalen Variablen, ohne dass eine Zwischendatei ( cpu.txt) beteiligt ist?

niemand
quelle

Antworten:

10

Auf einmal:

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

Das Obige nutzt die Prozessersetzung ( <()) und die Befehlssubstitution ( $()).

  • Die beiden Befehlsersetzungen werden durch das STDOUT der darin enthaltenen Befehle ersetzt

  • cpuidDer Befehl wird in die Prozessersetzung eingefügt. STDOUT wird als Dateideskriptor zurückgegeben, grepführt den erforderlichen Abgleich durch, wir haben grepmit PCRE ( -P) nur -oden gewünschten Teil ( ) abgerufen und -m1stoppt nach dem ersten Abgleich, um Wiederholungen zu vermeiden

  • printf wird verwendet, um die Ausgabe im gewünschten Format zu erhalten

Beispiel:

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

Sie können die Zwischendatei vermeiden, indem Sie eine Pipe verwenden , und Sie können beide vermeiden sedund awkindem Sie Ihren Abgleich und Ihre Ersetzung in awkz

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

Ohne Annahmen zu treffen und die Art der Stichprobe zu ändern, ist hier ein Rückgang des Ersatzes, der die Ausgabe wie gewünscht in einer Variablen speichert:

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

In der ersten Zeile wird die Variable CPUIDauf die Ausgabe von /usr/bin/cpuid
I gesetzt. Anschließend wird die Variable aals Ausgabe ( echo) der CPUIDin der obigen Zeile festgelegten Variablen festgelegt (dies wird dann an Ihre angegebenen Befehle weitergeleitet).

NGRhodes
quelle
1
Vielen Dank für die Erklärung. Dieser ist meinem Verständnis am nächsten. Leider bin ich kein Experte für Sed, Awk und Perl, aber ich habe ein anfängliches Verständnis. :-)
niemand
1
Das catin der ersten Zeile sollte nicht da sein. Dadurch wird der CPUID der Inhalt der ausführbaren Binärdatei und nicht deren Ausgabe zugewiesen.
Joe
0

sed

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

Da ich 8 Kerne habe, sendet mein PC Folgendes aus:

50  
50  
50  
50  
50  
50  
50  
50  

tac kehrt die Reihenfolge der Zeilen von cpuid um, so dass ich ^ CPU als Terminator eines CPU-Datensatzes verwenden kann. Ein ebenfalls erweitertes Modell und eine erweiterte Familie treten dann in der richtigen Reihenfolge auf

Sam Liddicott
quelle
0

Dies optimiert Ihre anfänglichen Befehle nicht, aber das Semikolon ermöglicht es Ihnen, zwei Befehle zusammenzusetzen, um die Verkettungsoperation vollständig zu vermeiden:

foo="$(firstcommand; secondcommand)"

Oder spezifisch für Ihre Situation:

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

Wenn Sie sich für die Zeilenumbrüche interessieren, sollten Sie vor dem ersten $(und nach dem Schließen doppelte Anführungszeichen setzen)

Peter Bowers
quelle
0

Hier ist eine Möglichkeit, dies zu tun awk(die gesamte Ausgabe erfolgt gemäß dem Code in Ihrer Antwort).

Wenn Sie am Ende immer wieder dieselbe Eingabe erneut verarbeiten, weist dies normalerweise darauf hin, dass ein anderer Ansatz möglicherweise besser ist.

awkist perfekt für die Verarbeitung von Texteingaben wie diese. awkProgramme sind viel länger als die Dinge, mit seddenen sie gemacht wurden , aber sie sind viel einfacher zu lesen und Sie können ihnen Druckanweisungen hinzufügen, um das Debuggen viel einfacher zu machen .

Ich habe meine Debugging-Anweisungen in (auskommentiert) gelassen. Sie können sie auskommentieren, um zu sehen, wie das Skript funktioniert.

Sie müssen das awkProgramm irgendwo platzieren, und der einfachste Ort in einem einzigen Anwendungsfall wie diesem ist, das Ganze in einer einfachen Zeichenfolge in Anführungszeichen in der awkBefehlszeile zu setzen.

Auf diese Weise müssen Sie es nicht in einer separaten Datei oder in einer temporären Datei speichern, sodass keine Dateiverwaltung erforderlich ist und das Skript für sich allein steht.

Dieses Programm sieht lang aus, aber es sind fast alle Kommentare, Debugging-Anweisungen und Leerzeichen.

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

Bisher lese ich alle Kommentare und werde versuchen, sie alle zu verwenden. Wie ich an NGRhodes schrieb: "Leider bin ich kein Experte für Sed, Awk und Perl, aber ich habe ein anfängliches Verständnis.

Vielen Dank an alle, die diese hervorragenden Beispiele gemacht / präsentiert haben. Ich hoffe aufrichtig, dass viel mehr Leute diese Zeilen lesen und ihre Skriptfähigkeiten vertiefen werden!

Eigentlich habe ich einen Cocktail von dem gemacht, was Sie mir alle vorgeschlagen haben:

/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

Ergebnis ist: 40651 0004-0651-0000-0000-0000-0000 was ich erwarte! :-)

niemand
quelle
Wenn Sie das alles tun und trotzdem awk verwenden, wäre es sauberer, das Ganze als kleines awk-Programm umzuschreiben. Siehe auch meinen Kommentar zu @NGRhodes Antwort, warum diese erste Zeile nicht funktioniert.
Joe