Use o comando sed para aplicar uma condição para verificar se um padrão foi correspondido

5

Estou pesquisando a string ::=BEGIN e quero aplicar uma condição para verificar se a palavra foi encontrada.

Então, o que quero dizer é algo ao longo destas linhas:

if (sed command does find a match for "::=BEGIN")
then i=1 
else i=0

Além disso, quero que o 1 (para sim encontrado) e 0 (não encontrado) sejam colocados na variável "i".

Por favor me ajude. Também forneça uma explicação para a solução! Obrigado!

    
por SamFlynn 11.06.2015 / 11:39

5 respostas

6

grep faz esse trabalho bem o suficiente.

$ echo "::=BEGIN" > testfile1.txt

$ grep "::=BEGIN" -q testfile1.txt && echo "FOUND"
FOUND

$ grep "::=BEGIN" -q testfile1.txt && echo "FOUND" || echo "NOTFOUND"
FOUND

$ grep "whever" -q testfile1.txt && echo "FOUND" || echo "NOTFOUND"
NOTFOUND

O que o código faz é simplesmente executar uma busca silenciosa no subshell. && , ou operando AND lógico, verifica se o primeiro comando foi bem-sucedido e, se ocorreu, ele executa echo "FOUND" . || verifica se esse eco foi executado, ou seja, se encontramos algo. O segundo eco é executado apenas se o primeiro comando falhar.

Aqui está uma versão awk :

$ awk '{i="NOTFOUND";if($0~/::=BEGIN/) i="FOUNDIT";exit } END { print i}' testfile1.txt
FOUNDIT

$ awk '{i="NOTFOUND";if($0~/whatevs/) i="FOUNDIT";exit } END { print i}' testfile1.txt
NOTFOUND

A ideia básica aqui é definir i to NOTFOUND e, se encontrarmos a string, altere-a para FOUNDIT . No final, depois que o primeiro conjunto terminar de processar o arquivo, imprimiremos i e nos informará se encontramos algo ou não.

Editar: No comentário mencionado, você deseja colocar o resultado em uma variável. O Shell já fornece uma variável que relata o status de saída do comando anterior, $0 . Sair do status 0 significa sucesso, tudo mais - falha. Por exemplo,

$ grep "::=BEGIN" -q testfile1.txt  
$ echo $?
0

Se você quiser usar o status de saída em uma variável, poderá fazer assim: MYVAR=$(echo $?) . Lembre-se, $? relatar o status de saída do comando anterior. Então você deve usar isso logo após o comando grep.

Se você ainda quiser usar os meus one-liners awk e grep anteriores, você pode usar o mesmo truque MYVAR=$() e colocar o comando que quiser entre as chaves. A saída será atribuída à variável MYVAR .

    
por Sergiy Kolodyazhnyy 11.06.2015 / 11:48
5

Com um GNU sed (como é instalado por padrão em qualquer sistema Ubuntu) :

{ sed -n '/::=BEGIN/Q 1'; i=$?; } <infile

Alguns fatos sobre essa resposta:

  1. sed Q uits entrada assim que a primeira correspondência é encontrada em qualquer lugar do arquivo - o que significa que não perca mais tempo continuando a ler o arquivo .

  2. sed retorna no código de saída do valor numérico 0 ou 1 dependendo se não poderia / poderia encontrar o regexp endereçado.

  3. $i está definido como sed ao retornar.

  4. O { grouping ; } é usado para tratar de forma robusta qualquer possível erro de redirecionamento - $i não é definido no caso do shell não poder abrir o arquivo, evitando falsos positivos.

Isso provavelmente não deve ser o preferido para grep -q , que basicamente pode também fazer todas as opções acima (se ao contrário) , faça isso POSIXly, e geralmente mais rápido.

A resposta grep -q já dada é muito boa, mas um pouco menor:

grep -q pattern ./infile; i=$((!$?))
    
por mikeserv 11.06.2015 / 19:41
3

Você pode usar isto:

#!/bin/bash
while IFS= read -r line; do
    case "$line" in *::=BEGIN*) i=1 && break;;         
                               *) i=0
    esac
done <file.txt

Isso pesquisará o arquivo file.txt linha por linha e, se uma correspondência de ::=BEGIN for encontrada, definirá a variável i=1 e sairá. Se nenhuma correspondência for encontrada, a variável será definida como i=0 .

    
por heemayl 11.06.2015 / 12:28
2

sed (Stream EDitor ) não é a ferramenta certa para esse tipo de coisa: basta usar uma instrução bash if para corresponder à sua entrada em relação a uma regex:

#!/bin/bash

#...
input="$(< inputfile)"
[[ "$input" =~ ::=BEGIN ]] && i=1 || i=0
#...
  • input="$(< inputfile)" : atribui o conteúdo de inputfile à variável $input
  • [[ "$input" =~ ::=BEGIN ]] && i=1 || i=0 : corresponde ao regex ::=BEGIN em relação ao conteúdo da variável $input ; se houver uma correspondência, ele atribuirá 1 a $i , caso contrário, atribuirá 0 a $i
por kos 11.06.2015 / 12:11
2

Minha sed versão

sed ':a;N;$!ba;s/\n/ /g' foo | sed '{/::=BEGIN/{s/.*/1/; b next}; s/.*/0/; :next}'

para armazenar em uma variável i :

i=$(sed ':a;N;$!ba;s/\n/ /g' foo | sed '{/::=BEGIN/{s/.*/1/; b next}; s/.*/0/; :next}')

Exemplo:

$ echo "::=BEGIN" > foo
$ echo "::=BEGIN" >> foo
$ sed ':a;N;$!ba;s/\n/ /g' foo | sed '{/::=BEGIN/{s/.*/1/; b next}; s/.*/0/; :next}' 
1
$ echo "::=NOT_BEGIN" > foo
$ sed ':a;N;$!ba;s/\n/ /g' foo | sed '{/::=BEGIN/{s/.*/1/; b next}; s/.*/0/; :next}'
0
$ echo "::=BEGIN" >> foo
$ sed ':a;N;$!ba;s/\n/ /g' foo | sed '{/::=BEGIN/{s/.*/1/; b next}; s/.*/0/; :next}' 
1

Explicação:

  • Se ::=BEGIN for encontrado, imprima um 1 e salte para next
  • Se ::=BEGIN não for encontrado, imprima 0
por A.B. 11.06.2015 / 14:24