Voici la partie du script bash
effectuant la découverte de cpuid
sous 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`
Ainsi, pour mon ordinateur portable, cette partie du script (illustrée ici) en donne 60.
Maintenant, comment faire cela en utilisant UNIQUEMENT des variables locales, sans fichier intermédiaire (cpu.txt
) impliqué?
En une fois:
printf '%s%s\n' "$(grep -Pom1 'extended model.*\(\K\d+' <(cpuid))" \
"$(grep -Pom1 'extended family.*\(\K\d+' <(cpuid))"
Ce qui précède exploite la substitution de processus (<()
) et la substitution de commande ($()
).
Les deux substitutions de commandes sont remplacées par le STDOUT des commandes à l'intérieur
La commande cpuid
est insérée dans la substitution de processus, le STDOUT sera renvoyé sous forme de descripteur de fichier, grep
fera la correspondance nécessaire, nous avons utilisé grep
avec PCRE (-P
) pour obtenir seulement (-o
) la portion souhaitée, et -m1
s'arrêtera après le premier match pour éviter les répétitions
printf
est utilisé pour obtenir la sortie au format souhaité
Exemple:
$ printf '%s%s\n' "$(grep -Pom1 'extended model.*\(\K\d+' <(cpuid))" "$(grep -Pom1 'extended family.*\(\K\d+' <(cpuid))"
30
Vous pouvez éviter le fichier intermédiaire en utilisant pipe, et vous pouvez éviter d'utiliser à la fois sed
et awk
en faisant votre correspondance et votre substitution dans awk
par exemple.
/usr/bin/cpuid |
awk '/extended model/ {mod = substr($4,3)} /extended family/ {fam = substr($4,3)}
END {printf "%d%d\n", mod, fam}'
Sans faire d'hypothèses et sans changer la nature de l'échantillon, voici une baisse de remplacement qui stocke la sortie dans une variable comme demandé:
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 } ')
La première ligne définit la variable CPUID
sur la sortie de /usr/bin/cpuid
J'ai ensuite défini la variable a
comme sortie (echo
) de la variable CPUID
définie dans la ligne ci-dessus (elle est ensuite acheminée vers les commandes fournies).
Jusqu'à présent, je lis tous les commentaires et je vais essayer de les utiliser tous. Comme je l’ai écrit à NGRhodes: "Malheureusement, je ne suis pas un expert pour sed, awk et Perl, mais une compréhension initiale que j’ai.
Un grand merci à tous ceux qui ont présenté/présenté ces excellents exemples. J'espère sincèrement que beaucoup plus de personnes liront ces lignes et approfondiront leurs compétences en matière de script!
En fait, j'ai préparé un cocktail de ce que vous m'avez tous suggéré:
/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
Le résultat est: 40651 0004-0651-0000-0000-0000-00 c'est ce que j'attends! :-)
Cela n'optimise pas vos commandes initiales, mais le point-virgule vous permet de mettre 2 commandes ensemble pour éviter entièrement l'opération de concaténation:
foo="$(firstcommand; secondcommand)"
Ou, spécifique à votre situation:
a=$(grep "extended model" $CPUID | sed 's/0x//' | awk ' { print $4 };
grep "extended family" $CPUID | sed 's/0x//' | awk ' { print $4 };)
Si vous vous souciez des nouvelles lignes, vous voudrez mettre des guillemets avant le $(
initial et après le )
final
sed
cpuid | tac | sed '/^CPU/{s/.*//;x;s/\n//g;p;d};/extended \(model\|family\)/!d;s/.*(\(.*\)).*/\1/;H;d'
comme j'ai 8 cœurs, mon pc émet:
50
50
50
50
50
50
50
50
tac inverse l'ordre des lignes de cpuid afin que je puisse utiliser ^ CPU comme terminateur d'un enregistrement de CPU, ainsi qu'un modèle et une famille étendus apparaissent dans le bon ordre.
Voici un moyen de le faire dans awk
(le résultat complet tel qu’indiqué par le code de votre réponse).
Lorsque vous finissez par traiter à nouveau la même entrée, cela indique généralement qu'une autre approche pourrait être meilleure.
awk
est parfait pour le traitement de texte tel que celui-ci. Les programmes awk
sont beaucoup plus longs que les opérations effectuées avec sed
, mais ils sont beaucoup plus faciles à lire et vous pouvez leur ajouter des instructions d'impression pour faciliter le débogage beaucoup.
J'ai laissé mes déclarations de débogage dans (commenté). Vous pouvez les commenter pour voir comment fonctionne le script.
Vous devez placer le programme awk
quelque part et, dans un cas d'utilisation unique comme celui-ci, le plus simple consiste à mettre le tout dans une seule chaîne entre guillemets sur la ligne de commande awk
.
De cette façon, vous n'avez pas besoin de le stocker dans un fichier séparé ou dans un fichier temporaire. Par conséquent, aucune gestion de fichier n'est nécessaire et le script est autonome.
Ce programme a l'air long, mais il contient presque tous les commentaires, les instructions de débogage et les espaces.
#!/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
}
'