Баш сценаріїв - як об'єднати наступні рядки?


8

Ось частина bashсценарію, що робить cpuidвідкриття в 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`

Отже, для мого ноутбука ця частина сценарію (показана тут) дає 60.

Тепер, як це зробити, використовуючи ТОЛЬКІ локальні змінні, не cpu.txtзадіяні проміжний файл ( )?

Відповіді:


10

За один раз:

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

Вищезазначене використовує процес заміщення ( <()) та підстановки команд ( $()).

  • Дві команди заміни замінюються STDOUT команд всередині

  • cpuidкоманда поміщена всередину заміни процесу, STDOUT буде повернуто як дескриптор файлу, grepзробить на ньому необхідну відповідність, ми використовували grepз PCRE ( -P), щоб отримати лише ( -o) потрібну частину, і -m1зупиниться після першого матчу, щоб уникнути повторення

  • printf використовується для отримання виводу в потрібному форматі

Приклад:

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

9

Ви можете уникнути проміжного файлу, використовуючи трубу , а ви можете уникнути використання обох sedі awk, виконуючи відповідність та заміну, awkнаприклад

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

1

Не роблячи припущень і не змінюючи характер вибірки, ось крапля заміни, яка зберігає результат у змінній, як вимагається:

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

Перший рядок встановлює змінну CPUIDдо виходу /usr/bin/cpuid
I, потім встановлює змінну aяк результат ( echo) CPUIDзмінної, встановленої у верхньому рядку (це потім передається в задані команди).


1
Дякую за пояснення. Цей є найближчим до мого рівня розуміння. На жаль, я не знаю седу, бува і перла, але я маю деякі початкові розуміння. :-)
ніхто

1
catУ першому рядку не повинно бути. Це призводить до того, що CPUID присвоює вміст двійкового виконуваного файлу, а не його вихід.
Джо

0

sed

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

оскільки у мене є 8 ядер, мій ПК випромінює:

50  
50  
50  
50  
50  
50  
50  
50  

tac перетворює порядок рядків з cpuid, щоб я міг використовувати ^ CPU як термінатор запису CPU, а також розширену модель і розширене сімейство потім відбуватись у правильному порядку


0

Це не оптимізує ваші початкові команди, але напівкрапка дозволяє скласти 2 команди разом, щоб уникнути операції конкатенації повністю:

foo="$(firstcommand; secondcommand)"

Або, конкретно для вашої ситуації:

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

Якщо ви дбаєте про нові рядки, вам потрібно буде поставити подвійні лапки перед початковим $(і після закриття)


0

Ось спосіб це зробити awk(цілий вихід, як це зроблено кодом у вашій відповіді).

Коли ви в кінцевому підсумку переробляєте один і той же вхід знову і знову, це зазвичай вказує на те, що інший підхід може бути кращим.

awkідеально підходить для такої обробки тексту. awkпрограми набагато довше, ніж це робиться з ними sed, але їх набагато простіше читати, і ви можете додавати до них заяви для друку, щоб набагато простіше налагодити.

Я залишив свої заяви про налагодження в (прокоментував). Ви можете коментувати їх, щоб подивитися, як працює сценарій.

Ви повинні помістити awkпрограму кудись, і найпростіше місце в одному випадку використання, як це - помістити всю справу в один цитований рядок у awkкомандному рядку.

Таким чином, вам не потрібно зберігати його в окремому файлі або у тимчасовому файлі, тому управління файлами не задіяне, і сценарій буде стояти самостійно.

Ця програма виглядає довго, але це майже всі коментарі, заяви про налагодження та пробіл.

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

Поки я читаю всі коментарі, і спробую їх усі використати. Як я писав до NGRhodes: "На жаль, я не знаю, що стосується sed, awk and perl, але я маю певне початкове розуміння.

Велике спасибі всім, хто зробив / представив ці чудові приклади. Я щиро сподіваюсь, що набагато більше людей прочитають ці рядки та поглиблюватимуть свої навички сценарію!

Насправді я зробив якийсь коктейль з того, що ви мені все запропонували:

/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

Результат: 40651 0004-0651-0000-0000-0000-0000 , що я очікую! :-)


Якщо ви все-таки будете робити все це і все-таки використовувати awk, то було б чистіше переписати всю справу як невелику програму awk. Також дивіться мій коментар до @NGRhodes відповідь, чому цей перший рядок не працює.
Джо
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.