
Eu tenho um arquivo onde tenho algumas linhas de informações 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
Quero extrair apenas os nomes dos países deste arquivo. Atualmente 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 nomes de países china, us
e au
, 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 forma clara de codificação, eu sei e, portanto, preciso da sua ajuda para extrair os nomes dos países de todas as linhas que contêm clean
ou raw
string.
Existe uma maneira de usar awk ou sed para extrair todos os nomes de países com duas chaves de correspondência? Minha saída deve ficar assim
china
india
us
uk
canada
au
Responder1
Eu não usaria um shell loop para processar texto.
Aqui, você pode simplesmente 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 _
caracteres e você quiser retornar a parte da linha entre a primeira _
e a primeira ocorrência _raw
ou _clean
depois disso, você poderia fazer:
perl -ne 'print $1 if s/^[^_]*_(.*?)_(clean|raw)/' < country.txt
Ou com GNU grep
:
grep -Po '^[^_]*_\K.*?(?=_clean|_raw)' < country.txt
Com -P
(desde que grep
tenha sido construído com suporte PCRE), o regexp é compatível com Perl. Nessas regexps, \K
redefine o início da string correspondente e (?=...)
é um operador lookahead, ou seja, verifica se o restante da string corresponde ...
sem que essa parte seja incluída na parte correspondente. -o
gera grep
a saída da parte correspondente, então aqui ele imprime o que corresponde ao .*?
acima, que é o equivalente não ganancioso de .*
, que é uma sequência de 0 ou mais caracteres, o mais curto possível, neste caso seguindo uma sequência de 0 ou mais sublinhados ( [^_]*
) encontrado no início da linha ( ^
) seguido por um sublinhado e assumindo que seja seguido por _raw
ou _clean
.
Com pcregrep
, você também pode escrever:
pcregrep -o1 '^[^_]*_(.*?)_(clean|raw)'
Com -o1
, ele imprime a parte correspondente ao primeiro (...)
.
Responder2
Aqui está o caminho no estilo awk
awk -F'_' '/clean|raw/{ print $2}'