Um trecho de um arquivo tsv típico que usei
10 Interstellar Main Theme Extended UDVtMYqUAyw
11 Journey XvG78AmBLc4
12 Jurassic Park Music & Ambience Amazing Soundscapes and Music PPl__iyIg6w
13 Lord of the Rings Sound of The Shire chLZQtCold8
14 Lord of the Rings The Shire: Sunset at Bag End uBmbI8dzc-M
As seguintes pesquisas por senhor (sem distinção entre maiúsculas e minúsculas) na 2ª coluna de todos os arquivos tsv:
awk '$2~IGNORECASE = 1;/lord/{print}' *.tsv
13 Lord of the Rings Sound of The Shire chLZQtCold8
14 Lord of the Rings The Shire: Sunset at Bag End uBmbI8dzc-M
Agora, eu queria passar Lord
como uma variável de ambiente bash:
$ awk -v Pattern="Lord" '$2~Pattern{print}' *.tsv
13 Lord of the Rings Sound of The Shire chLZQtCold8
14 Lord of the Rings The Shire: Sunset at Bag End uBmbI8dzc-M
Problema
Como fazer a correspondência de maiúsculas e minúsculas de forma insensível?
Eu tentei o seguinte, mas não funciona
awk -v Pattern="lord" '$2~IGNORECASE = 1;Pattern{print}' *.tsv
awk -v Pattern="lord" 'IGNORECASE = 1;$2~Pattern{print}' *.tsv
awk -v Pattern="lord" 'BEGIN {IGNORECASE = 1} {$2~Pattern{print}}' *.tsv
awk -v Pattern="Lord" '{IGNORECASE = 1; $2~Pattern}' *.tsv
Referir
Responder1
Em primeiro lugar, duvido que $2~IGNORECASE = 1;/lord/{print}
funcione da maneira que você pensa - AFAIK atribui valor 1
à variável IGNORECASE
; compara o valor de $2
com o resultado (ou seja $2 ~ 1
, ) e por padrão imprime $0
se o resultado for verdadeiro; em seguida, compara $0
sem distinção entre maiúsculas e minúsculas /lord/
etambémimprime $0
se isso for verdade.
Se sua intenção é comparar $2
sem distinção entre maiúsculas e minúsculas, você pode usar
gawk 'BEGIN{IGNORECASE = 1} $2 ~ /lord/{print}` *.tsv
ou apenas
gawk 'BEGIN{IGNORECASE = 1} $2 ~ /lord/` *.tsv
O equivalente com uma variável seria
gawk -v Pattern="lord" 'BEGIN{IGNORECASE = 1} $2 ~ Pattern' *.tsv
Observe que IGNORECASE
não é um recurso padrão do awk - até onde eu sei, apenas o GNU awk( gawk
) o suporta - para portabilidade você pode usar toupper
ou tolower
para obter a entrada em um caso específico.
Responder2
Em relação a The following searches for lord (case insensitively) in 2nd column of all tsv files: awk '$2~IGNORECASE = 1;/lord/{print}' *.tsv
- não, não faz nada disso. Ele faz uma comparação regexp de $2 com o resultado da atribuição de IGNORECASE a 1, que é sempre verdadeiro, e assim imprime a linha atual. Em seguida, ele procura qualquer string que corresponda ao regexp lord
em qualquer lugar da linha e imprime a linha uma segunda vez. Você provavelmente pretendia fazer awk 'BEGIN{IGNORECASE = 1} $2~/lord/' *.tsv
o que descreve.
Não use a palavra “padrão” neste contexto, pois é altamente ambígua. Você está usando Pattern como uma correspondência parcial de regexp, mas descrevendo-o como se quisesse uma correspondência de string de palavra completa. Portanto, substitua "padrão" por todos os 3 string-ou-regexp e parcial ou completo e palavra ou linha em todos os lugares em que ocorrer em sua pergunta para que possamos ajudá-lo a encontrar a solução certa. Vercomo-faço-para-encontrar-o-texto-que-corresponde-a-um-padrãoPara maiores informações.
Aqui estão algumas soluções possíveis para o que você pode estar tentando fazer:
Correspondência parcial de strings:
$ awk -v var="$var" -F'\t' 'index(tolower($2),tolower(var))' file.tsv
13 Lord of the Rings Sound of The Shire chLZQtCold8
14 Lord of the Rings The Shire: Sunset at Bag End uBmbI8dzc-M
Correspondência de string de palavra completa:
$ awk -v var="$var" -F'\t' 'index(" "tolower($2)" ",tolower(var))' file.tsv
13 Lord of the Rings Sound of The Shire chLZQtCold8
14 Lord of the Rings The Shire: Sunset at Bag End uBmbI8dzc-M
Correspondência de string de linha completa:
$ awk -v var="$var" -F'\t' 'tolower($2) == tolower(var)' file.tsv
$
Correspondência parcial de regexp:
$ awk -v var="$var" -F'\t' 'tolower($2) ~ tolower(var)' file.tsv
13 Lord of the Rings Sound of The Shire chLZQtCold8
14 Lord of the Rings The Shire: Sunset at Bag End uBmbI8dzc-M
Correspondência de regexp de palavra completa:
$ awk -v var="$var" -F'\t' '(" "tolower($2)" ") ~ tolower(var)' file.tsv
13 Lord of the Rings Sound of The Shire chLZQtCold8
14 Lord of the Rings The Shire: Sunset at Bag End uBmbI8dzc-M
Correspondência de regexp de linha completa:
$ awk -v var="$var" -F'\t' 'tolower($2) ~ ("^"tolower(var)"$")' file.tsv
$
O texto acima pressupõe que sua variável shell não contém sequências de escape ou, se desejar, você deseja que elas sejam expandidas. Se não for esse o caso, use ENVIRON[]
ou ARGV[]
para passar o valor da variável shell para awk em vez de -v
, consultecomo faço para usar variáveis shell em um script awkpara detalhes.
Responder3
Com perl
:
Procurando um padrão no segundo campo do arquivo:
perl -F"\t" -lane '$F[1] =~ /(?i)lord/ and print' input.tsv
-F"\t"
é porque o arquivo é tsv$F[1]
é o segundo arquivo de registro porque os campos são indexados em zero.(?i)
é uma opção que não diferencia maiúsculas de minúsculas em regex- ou modificador
i
pode ser usado para insensibilidade a maiúsculas e minúsculas, como em
perl -F"\t" -lane '$F[1] =~ /lord/i and print' input.tsv
regex correspondente a uma variável shell pode ser feito export
como em
export p=lord
perl -F"\t" -lane '$F[1] =~ /(?i)$ENV{p}/ and print' input.tsv
perl -F"\t" -lane '$F[1] =~ /$ENV{p}/i and print' input.tsv
Pesquisando em todos .tsv
os arquivos de uma pasta:
perl -F"\t" -lane '$F[1] =~ /$ENV{p}/i and print' *.tsv
Se você quiser um nome de arquivo com registros, o seguinte seria o suficiente:
perl -F"\t" -lane '$F[1] =~ /$ENV{p}/i and print $ARGV. ":" .$_' *.tsv
Responder4
Se você não precisa usarestranhoe pode usar uma ferramenta dedicada ao processamento de dados tabulares, comoGoCSV, isso é muito fácil.
Começando com a amostra de dados que você forneceu, inventei alguns nomes e adivinhei "Journey":
entrada.tsv
EU IA | Álbum | Acompanhar | Cerquilha |
---|---|---|---|
10 | Interestelar | Tema principal estendido | UDVtMYqUAyw |
11 | Jornada | XvG78AmBLc4 | |
12 | Música e ambiente do Jurassic Park | Paisagens sonoras e músicas incríveis | PPl__iyIg6w |
13 | Senhor dos Anéis | Som do Condado | chLZQtCold8 |
14 | Senhor dos Anéis | The Shire: Pôr do sol em Bolsão | uBmbI8dzc-M |
- definir a variável shell
pattern
- deslimpara converter o TSV para CSV
- filtrona coluna 2 com o-eu invariante de caso --regexdaquela variável shell
- decapitarpara obter apenas as linhas correspondentes
- converter de volta para TSV:
pattern='lord'
gocsv delim -i "\t" input.tsv \
| gocsv filter -c 2 -i --regex "$pattern" \
| gocsv behead \
| gocsv tsv
13 Lord of the Rings Sound of The Shire chLZQtCold8
14 Lord of the Rings The Shire: Sunset at Bag End uBmbI8dzc-M