vários padrões com sed (regex AND ou condição)

3

Eu quero remover os dados indesejados. Então, minha pergunta é como excluir linhas acima de test1 se ele não contém test1 OR não terminou com uma cotação?

20  /test1/catergory="Food"
20  /test1/target="Adults, \"Goblins\", Elderly,
Babies, \"Witch\",
Faries"
**This is some unwanted data to remove**
20  /test1/type="Western"
20  /test1/end=category
**This is some unwanted data to remove**
20  /test1/Purpose=
20  /test1/my_purpose="To create 
a fun-filled moment"
20  /test1/end=Purpose

Resultado esperado:

20  /test1/catergory="Food"
20  /test1/target="Adults, \"Goblins\", Elderly,
Babies, \"Witch\",
Faries"
20  /test1/type="Western"
20  /test1/end=category
20  /test1/Purpose=
20  /test1/my_purpose="To create 
a fun-filled moment"
20  /test1/end=Purpose

Eu estava preso a estes poucos comandos:

1. grep -B1 'test1' test_long_sentence.txt
2. sed '/test1/!d' test_long_sentence.txt 
3. sed '/\"$/!d' test_long_sentence.txt

Eu não sei como combinar não. 2 e 3 (sed com vários comandos com regex e condição OR)

    
por Jojoleo 13.02.2018 / 03:22

1 resposta

4

lex (ou flex em sistemas Linux) é um programa que usa uma especificação de scanner / lexer e o transforma em um programa em C. Sua especificação de scanner é similar em natureza a um programa awk , mas onde awk é orientado a registro lex é "orientado a caracteres".

Usando lex com a seguinte fonte em lexer.l :

%x OUTPUT
%%
                        int quoted = 0;

^[0-9]*[ \t]*"/test1/"  { BEGIN OUTPUT;             ECHO; }
<OUTPUT>\n              { if (!quoted) { BEGIN 0; } ECHO; }
<OUTPUT>[^\]["]        { quoted = !quoted;         ECHO; }
<OUTPUT>.               {                           ECHO; }
.|\n                    ;

Este scanner usa um estado OUTPUT para acompanhar se queremos que os caracteres atuais sejam exibidos ou não. Entramos nesse estado com BEGIN OUTPUT quando encontramos uma linha parecida com

<number>  /test1/

(isso é tratado pela primeira regra). Saímos desse estado quando uma linha termina e não estamos verificando uma string entre aspas (isso é tratado pela segunda regra).

Uma string entre aspas é iniciada e finalizada com um caractere " não escapado (a terceira regra). Todos os outros caracteres são transmitidos como estão sem ação (a quarta regra).

Embora não esteja no estado OUTPUT , ignoramos tudo (a última regra).

Note que este é um scanner improvisado escrito para seus dados específicos. Ele não manipula strings entre aspas que terminam com uma barra invertida com escape ( "some data \" ), mas funciona nos dados que você mostrou.

Construindo:

$ make lexer
lex  -o lex.lexer.c lexer.l
cc -O2 -pipe    -o lexer lex.lexer.c  -ll
rm -f lex.lexer.c

(no Linux, ao usar flex , você pode ter que usar make lexer LDLIBS=-ll )

Usando:

$ ./lexer <file
20  /test1/catergory="Food"
20  /test1/target="Adults, \"Goblins\", Elderly,
Babies, \"Witch\",
Faries"
20  /test1/type="Western"
20  /test1/end=category
20  /test1/Purpose=
20  /test1/my_purpose="To create
a fun-filled moment"
20  /test1/end=Purpose
    
por 31.05.2018 / 12:47