Como grep uma linha se incluir algumas strings?

0

Eu tenho um arquivo de configurações chamado estudante

grade1 class1 11 student
grade1 class1 12 student
grade2 class1 21 student
grade2 class2 22 student
......

Agora eu crio um arquivo test.sh para ler o aluno. Se a entrada gradename e studentnumber, a linha incluir duas strings será copiada para student_copy . O código será como:

echo Input gradename and studentnumber
read gradename
read studentnumber

if (input gradename and studnetnumber);
then
    echo "the line include them" >> student_copy

Por exemplo:

if (input grade1 and 11);
then 
    echo grade1 class1 11 student >> student_copy
    
por Zhang Kai 08.01.2018 / 04:30

4 respostas

6

grep não faz operações AND lógicas (por exemplo, match patternA AND patternB ), o mais próximo que você pode chegar é construir um regexp mais longo que corresponda a qualquer uma das variações possíveis (por exemplo, grep -E 'patternA.*patternB|patternB.*patternA' ). Isso fica muito desajeitado e pesado se você tiver muitos padrões para combinar.

A maneira mais fácil de fazer o que você deseja é usar uma linguagem de script como awk ou perl em vez de grep .

por exemplo. o seguinte awk one-liner corresponderá a qualquer linha em que ambos os padrões sejam exibidos.

awk '/patternA/ && /patternB/'

Qualquer uma das correspondências de padrão pode ser invertida também, por exemplo, se você quiser corresponder qualquer linha que contenha patternA que não contenha patternB (ou seja, uma operação AND NOT ):

awk '/patternA/ && ! /patternB/'

Nota: uma abordagem ingênua é usar grep patternA | grep patternB (ou grep patternA | grep -v patternB ) - que faz atingir um AND lógico (ou AND NOT), mas com o custo de executar vários comandos grep em vez de um único comando awk ou perl .

    
por 08.01.2018 / 04:59
1

Digamos que queremos encontrar linhas com grade1 e 11 :

Dados de amostra (não é o mesmo que na pergunta) e chaves de pesquisa:

$ cat student
grade1 class1 11 student
grade1 class1 111 student
grade11 class1 21 student
grade12 class2 22 student
$ grade=grade1
$ num=11

Direto ao grep para procurar pelas strings dadas, observe as âncoras \< / \> que correspondem às bordas das palavras. Isso precisa deles em ordem:

$ grep "^$grade\>.*\<$num\>" student
grade1 class1 11 student

Ou com -w para corresponder às palavras completas.

$ < student grep -w "$grade" |grep -w "$num"
grade1 class1 11 student

Ambos os itens acima podem corresponder a palavras parecidas similares em outros lugares nas linhas, então talvez seja melhor fazê-lo com o awk e comparar apenas os campos apropriados. Isso pressupõe que os campos são separados por espaços em branco, portanto eles não podem conter nenhum espaço em branco em si.

$ awk -vg=$grade -vn=$num '$1 == g && $3 == n' student
grade1 class1 11 student

Se você precisa ter campos com espaços, seria melhor ter um separador distinto, como uma guia.

    
por 08.01.2018 / 12:33
0

Eu corro este comando abaixo,

awk '{
if ($1!="grade1" || $3!=11)
print "###";
else
print $0;
}' student

a saída é

grade1 class1 11 student
###
###
###

qual é o resultado esperado

mas se eu executar test.sh , o código está abaixo:

read -p "Enter gradename: " gradename
read -p "Enter studentnumber: " studentnumber

echo "gradename = $gradename"
echo "studentnumber = $studentnumber"
awk '{
if ($1!="$gradename" || $3!=$studentnumber)
print "###";
else
print $0;
}' student > student2

cat student2

a saída será:

Enter gradename: grade1
Enter studentnumber: 11
gradename = grade1
studentnumber = 11
###
###
###
###

É muito estranho

    
por 08.01.2018 / 10:04
0

Abaixo awk um forro eu usei para encontrar o mesmo e funciona bem

 for i  in 'awk '{print $1}' student.txt| sed -r "s/\s+//g"| sed '/^$/d'| sort -u' ; do awk -v i="$i" '$1 ~ i && $3 == "11"{print $0}'  student.txt ; done

Eu verifiquei o número 11 do estudante como constante, então mencionei $ 3 == 11 no script.

nota 1 e nota 2 como variável em "i"

Você pode alterar o número do aluno de acordo com sua necessidade. Altere o valor de $ 3 == "New Student number" de acordo com o requisito

    
por 08.01.2018 / 12:00