Bash scripting - como concatenar as seguintes strings?

8

Aqui está a parte do script bash fazendo cpuid discovery no Linux (Ubuntu / Fedora):

/usr/bin/cpuid > id.txt    
CPUID=id.txt    
echo 'grep "extended model" $CPUID' | sed 's/0x//' | awk ' { print  } ' > cpu.txt    
a='cat cpu.txt'    
echo 'grep "extended family" $CPUID'| sed 's/0x//' | awk ' { print  } ' > cpu.txt    
a+='cat cpu.txt'

Então, para o meu laptop, essa parte do script (mostrada aqui) dá 60.

Agora, como fazer isso usando APENAS variáveis locais, não tendo arquivo intermediário ( cpu.txt ) envolvido?

    
por nobody 05.10.2016 / 16:40

7 respostas

10

De uma só vez:

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

O exemplo acima utiliza a substituição do processo ( <() ) e a substituição de comando ( $() ).

  • As duas substituições de comando são substituídas pelo STDOUT dos comandos dentro

  • O comando
  • cpuid é colocado dentro da substituição do processo, o STDOUT será retornado como um descritor de arquivo, grep fará a correspondência necessária, usamos grep com PCRE ( -P ) para obter apenas ( -o ) a parte desejada, e -m1 parará após a primeira correspondência para evitar a repetição

  • printf é usado para obter a saída no formato desejado

Exemplo:

$ printf '%s%s\n' "$(grep -Pom1 'extended model.*\(\K\d+' <(cpuid))" "$(grep -Pom1 'extended family.*\(\K\d+' <(cpuid))"
30
    
por heemayl 05.10.2016 / 17:03
9

Você pode evitar o arquivo intermediário usando um pipe e pode evitar usar sed e awk fazendo sua correspondência e substituição em awk , por exemplo,

/usr/bin/cpuid | 
  awk '/extended model/ {mod = substr(,3)} /extended family/ {fam = substr(,3)} 
  END {printf "%d%d\n", mod, fam}'
    
por steeldriver 05.10.2016 / 19:41
1

Sem fazer suposições e mudar a natureza da amostra, aqui está uma queda na substituição que armazena a saída em uma variável conforme solicitado:

CPUID=$(/usr/bin/cpuid)
a=$(echo "$CPUID" | grep 'extended model' | sed 's/0x//' | awk ' { print  } ')
a+=$(echo "$CPUID" | grep 'extended family' | sed 's/0x//' | awk ' { print  } ')

A primeira linha define a variável CPUID para a saída de /usr/bin/cpuid
Em seguida, defino a variável a como a saída ( echo ) da variável CPUID definida na linha acima (isso é canalizado para os comandos fornecidos).

    
por NGRhodes 05.10.2016 / 21:42
0

sed

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

como eu tenho 8 núcleos, meu pc emite:

50  
50  
50  
50  
50  
50  
50  
50  

tac inverte a ordem das linhas do cpuid para que eu possa usar ^ CPU como um terminador de um registro de CPU, um modelo também estendido e a família estendida então ocorrem na ordem correta

    
por Sam Liddicott 05.10.2016 / 20:39
0

Isso não otimiza seus comandos iniciais, mas o ponto e vírgula permite que você coloque 2 comandos juntos para evitar a operação de concatenação:

foo="$(firstcommand; secondcommand)"

Ou específico da sua situação:

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

Se você se preocupa com as novas linhas, você vai querer colocar aspas duplas antes da inicial $( e depois do fechamento )

    
por Peter Bowers 06.10.2016 / 07:49
0

Aqui está uma maneira de fazer isso em awk (toda a saída como feita pelo código na sua resposta).

Quando você acaba reprocessando a mesma entrada várias vezes, isso geralmente indica que outra abordagem pode ser melhor.

awk é perfeito para processar entrada de texto como esta. Os programas awk são muito mais longos do que os feitos com sed , mas são muito mais fáceis de ler e você pode adicionar instruções de impressão a eles para facilitar a depuração .

Deixei minhas instruções de depuração em (comentadas). Você pode descomentá-los para ver como o script funciona.

Você tem que colocar o programa awk em algum lugar e o lugar mais fácil em um único caso de uso é colocar a coisa toda em uma única string entre aspas na linha de comando awk .

Dessa forma, você não precisa armazená-lo em um arquivo separado ou em um arquivo temporário, portanto, não há gerenciamento de arquivos envolvido e o script ficará por conta própria.

Este programa parece longo, mas são quase todos os comentários, instruções de depuração e espaço em branco.

#!/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(, 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(, 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")
 == "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")
 == "model" && mo == "" {
  mo = substr(, 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(, 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 = 
  ##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
}
'
    
por Joe 13.10.2016 / 05:09
0

Até agora, estou lendo todos os comentários e tentarei usar todos eles. Como eu escrevi para NGRhodes: "infelizmente, eu não sou especialista em sed, awk e perl, mas em algum entendimento inicial eu tenho.

Muito obrigado a todos que fizeram / apresentaram esses excelentes exemplos. Eu sinceramente espero que muito mais pessoas leiam estas linhas e aprofundem suas habilidades de script!

Na verdade, eu fiz um coquetel do que vocês me sugeriram:

/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  } '')  
a+=$(echo 'cat $CPUID | grep -m1 'extended family' | sed 's/0x//' | awk ' { print  } '')  
a+=$(echo 'cat $CPUID | grep -m1 'AMD' | sed 's/(//' | sed 's/)//' | awk ' { print  } '')  
a+=$(echo 'cat $CPUID | grep -m1 'model' | sed 's/0x//' | awk ' { print  } '')  
a+=$(echo 'cat $CPUID | grep -m1 'stepping id' | sed 's/0x//' | awk ' { print  } '')  
a+=' '  
a+=$(echo 'cat $CPUID | grep -m1 'processor serial number:' | awk ' { print  } '')  
echo $a

O resultado é: 40651 0004-0651-0000-0000-0000-0000 que é o que eu espero! : -)

    
por nobody 13.10.2016 / 05:25