Linux_hämta version
Jag har försökt på många sätt för att hämta Linuxversionen från lsb_release -a med hjälp av kommandot awk. Resultatet blir dock inte det jag strävar efter.
Skriver jag lsb_release -a blir outputen så här:
Hur ska jag göra om jag vill endast skriva ut "Ubuntu 21.10" med hjälp av awk-kommandot ?
Som alltid finns det otal olika sätt. awk är kraftfullt men å andra sidan kan man inte vara expert på alla kommandon i alla verktygsprogram. Ett relativt enkelt sätt att använda awk är att skriva program med C-syntax (åtminstone enkelt om man kan C eller Java). Det finns mer kompakta sätt som använder inbyggda funktioner i awk men jag har själv aldrig brytt mig om mer än några stycken.
Så här kan man göra med awk:
lsb_release -a 2>/dev/null|awk '{if ($1 == "Description:") { for(i=2;i<=NF;i++){printf("%s ", $i)} printf("\n")}}'
2>/dev/null är för att få bort fel/info som skrivs till stderr (t ex "No LSB modules are available")
Sen följer ett uttryck som ser ut ungefär som ett C-program.
$0 är hela raden, $1 är första fältet, $2 andra fältet osv. awk delar upp raden vid varje field separator, den är space som default (-F för att ändra)
NF är antal fält.
printf() medger formatering (ren "print $i" skriver ut radbryt också)
if ($1 == "Description:") {
for (i=2; i<=NF; i++) {
printf("%s ", $i)
}
printf("\n")
}
En ful detalj ovan är att ett extra space kommer skrivas ut sist på raden, det kan man undvika med en extra "if" som kolla om i+1<NF och då skriver space. Och det blev ganska långt.
Men vi kan använda att kolumnerna är separerade med tab:
lsb_release -a 2>/dev/null|awk -F '\t' '{if ($1 == "Description:") print $2}'
Mycket kompaktare och snyggare.
Om frågan vidgas så att man inte måste använda awk skulle min första tanke vara att använda grep och sed. Inte mer kompakt, bara ett exempel på att det finns många olika sätt att få fram det man vill ha:
lsb_release -a 2>/dev/null|grep 'Description:'|sed 's/Description:\t//g'
grep väljer rätt rad
sed har en lika omfattande uppsättning möjligheter som awk men ska man kunna endast ett kommando är det "match and replace":
"s/MATCH/REPLACE/g"
MATCH: regex sed letar efter, här strängen "Description" följt av tab
REPLACE: vad vi ersätter med, här tomma strängen
g är "global", onödigt i detta fall men oftast vill man göra operationen på alla matchande ställen och inte bara på första i raden
Ovanstående kan förkortas till
lsb_release -a 2>/dev/null|grep 'Description'|sed 's/.*[\t]//g'
sed-uttrycket matchar nu "vad som helst" följt av tab
Programmeraren skrev:Som alltid finns det otal olika sätt. awk är kraftfullt men å andra sidan kan man inte vara expert på alla kommandon i alla verktygsprogram. Ett relativt enkelt sätt att använda awk är att skriva program med C-syntax (åtminstone enkelt om man kan C eller Java). Det finns mer kompakta sätt som använder inbyggda funktioner i awk men jag har själv aldrig brytt mig om mer än några stycken.
Så här kan man göra med awk:
lsb_release -a 2>/dev/null|awk '{if ($1 == "Description:") { for(i=2;i<=NF;i++){printf("%s ", $i)} printf("\n")}}'
2>/dev/null är för att få bort fel/info som skrivs till stderr (t ex "No LSB modules are available")
Sen följer ett uttryck som ser ut ungefär som ett C-program.
$0 är hela raden, $1 är första fältet, $2 andra fältet osv. awk delar upp raden vid varje field separator, den är space som default (-F för att ändra)
NF är antal fält.
printf() medger formatering (ren "print $i" skriver ut radbryt också)if ($1 == "Description:") { for (i=2; i<=NF; i++) { printf("%s ", $i) } printf("\n") }
En ful detalj ovan är att ett extra space kommer skrivas ut sist på raden, det kan man undvika med en extra "if" som kolla om i+1<NF och då skriver space. Och det blev ganska långt.
Men vi kan använda att kolumnerna är separerade med tab:
lsb_release -a 2>/dev/null|awk -F '\t' '{if ($1 == "Description:") print $2}'
Mycket kompaktare och snyggare.
Om frågan vidgas så att man inte måste använda awk skulle min första tanke vara att använda grep och sed. Inte mer kompakt, bara ett exempel på att det finns många olika sätt att få fram det man vill ha:
lsb_release -a 2>/dev/null|grep 'Description:'|sed 's/Description:\t//g'
grep väljer rätt rad
sed har en lika omfattande uppsättning möjligheter som awk men ska man kunna endast ett kommando är det "match and replace":
"s/MATCH/REPLACE/g"
MATCH: regex sed letar efter, här strängen "Description" följt av tab
REPLACE: vad vi ersätter med, här tomma strängen
g är "global", onödigt i detta fall men oftast vill man göra operationen på alla matchande ställen och inte bara på första i radenOvanstående kan förkortas till
lsb_release -a 2>/dev/null|grep 'Description'|sed 's/.*[\t]//g'
sed-uttrycket matchar nu "vad som helst" följt av tab
Tack så mycket för dina lösningar och speciellt förklaringarna! Jag löste faktiskt själv problemet med något likt din andra lösning. Det som jag körde fast vid var field separatorn när det är tab.
Jag gjorde så här:
lsb_release -a | sed -n '/Description/s/^.*:[\t ]*//p'
Laguna skrev:Jag gjorde så här:
lsb_release -a | sed -n '/Description/s/^.*:[\t ]*//p'
Så här blir resultatet med din lösning:
Den första raden ska på något vis tas bort. Jag tror att det behövs att klämma in ett grepp-kommando mellan första och andra kommandon, som endast plockar raden innehållande "Description", eller fånga upp det första felmeddelandet genom att skriva lsb_release -a 2>/dev/null
Aha. Ja, felmeddelanden var jag inte beredd på, men det är inte säkert att man vill ignorera dem. Vad returnerar kommandot för statuskod i det fallet?
Laguna skrev:Aha. Ja, felmeddelanden var jag inte beredd på, men det är inte säkert att man vill ignorera dem. Vad returnerar kommandot för statuskod i det fallet?
När jag kör med echo $? för statuskoden så får jag 0 !!! Hur hänger det ihop med om det är ett felmeddelande med statuskoden 0 ?
Det är bara en information om att det inte finns något. Programmet ser inte det som ett error.
Om du kollar man-bladet, "man lsb_release
", så ser du att du kan be om annan info mer specifikt med t exlsb_release -d
Program kan skriva varningar på stderr och annat på stdout, men det skulle vara bra om det framgick att "No LSB modules available" var en varning.