Como extrair linhas se qualquer uma das duas sequências de caracteres coincidir?

0

Eu tenho um arquivo em que tenho poucas linhas de informação que contêm o nome do país, conforme mostrado abaixo.

$cat country.txt

max_china_clean_foo
man_india_raw_bar
max_us_clean_bax
max_uk_raw_bar
max_canada_raw_foo
max_au_clean_bar

Eu quero extrair apenas os nomes dos países desse arquivo. No momento, estou usando o código abaixo para extrair o nome do país em um loop for

val=${val#*_}
val=${val%_clean*}
echo $val

Mas a saída produzida tem apenas china, us e au nomes de países e, portanto, tenho que repetir o código semelhante com pequenas modificações para extrair os países restantes, como abaixo

val=${val#*_}
val=${val%_raw*}
echo $val

Esta não é uma maneira clara de codificação, eu sei e, portanto, preciso da sua ajuda para extrair os nomes dos países de todas as linhas que possuem clean ou raw string.

Existe uma maneira de usar o awk ou o sed para extrair todos os nomes de países com duas chaves de correspondência? Minha saída deve se parecer com isso

china
india
us
uk
canada
au
    
por Alex Raj Kaliamoorthy 03.10.2016 / 17:26

2 respostas

2

Eu não usaria um loop de shell para processar texto .

Aqui, você pode apenas fazer:

cut -d _ -f 2 < country.txt

Ou se a entrada puder conter linhas sem _ caracteres:

awk -F _ 'NF >= 2 {print $2}' < country.txt

Se o nome do país puder conter o caractere _ e você quiser, em vez disso, retornar a parte da linha entre o primeiro _ e a primeira ocorrência de _raw ou _clean , você poderá fazer:

perl -ne 'print $1 if s/^[^_]*_(.*?)_(clean|raw)/' < country.txt

Ou com o GNU grep :

grep -Po '^[^_]*_\K.*?(?=_clean|_raw)' < country.txt

Com -P (desde que grep tenha sido criado com suporte a PCRE), o regexp é compatível com perl. Nesses regexps, \K redefine o início da string correspondida e (?=...) é um operador de look-ahead, ou seja, o restante da string corresponde a ... sem que essa parte seja incluída na parte correspondente. -o torna grep a saída da porção casada, então aqui imprime o que corresponde ao .*? acima, que é o equivalente não-ganancioso de .* , que é uma sequência de 0 ou mais caracteres, o mais curta possível, neste caso, seguindo uma sequência de 0 ou mais sublinhados ( [^_]* ) encontrados no início da linha ( ^ ) seguidos por um sublinhado e supondo que seja seguido por _raw ou _clean .

Com pcregrep , você também pode escrevê-lo:

pcregrep -o1 '^[^_]*_(.*?)_(clean|raw)'

Com -o1 , imprime a parte correspondida pelo primeiro (...) .

    
por 03.10.2016 / 17:59
0

Aqui está o caminho no estilo awk

awk -F'_' '/clean|raw/{ print $2}'
    
por 03.10.2016 / 18:06