
#nomedoarquivo como $1
#nome comercial como $2
#atualizado no ano $3 #Pode corresponder a qualquer vírgula dentro dos valores de cotação, desde que esteja antes do V correspondente para o código postal. Todos eles começam com V.
./script6_1.sh bcindigenousbusinesslistings.csv "B.*" 2021
Para encontrar todos os negócios que começam com B atualizados em 2020 ou posteriormente.
#O primeiro sed é para colocar da linha 2 até a última linha #O segundo sed : No início da linha, pode corresponder a qualquer padrão até o V (código postal) então irá parar $3 irá corresponder a qualquer número que tem padrão de 20(1 a 3) e (0-9) para o último dígito
*sed -n '2,$p' $1 | sed -e 's/^\('$2'[^,]*,[^,]*,[^,]*,.*[^V],\)\('$3'202[0-9]\)/\1\2/'*
O ponto principal é extrair 3 colunas, cada uma separada por vírgulas. Negócio, descrição, endereço. A última coluna é Ano atualizado. Dentro da descrição da coluna, pode haver mais vírgulas separadas.
Estou tendo um erro nisso, pois apenas imprime toda a linha, sem extrair o padrão correspondente.
Responder1
Se você quiser trabalhar com colunas dentro de uma linha em vez de com a linha inteira, então awk
or perl
seria uma ferramenta muito melhor para esse trabalho do que sed
.
E, como você precisa lidar com campos entre aspas (com vírgulas dentro deles), seria melhor usar perl
porque tem umTexto::CSVmódulo que analisa arquivos CSV assim. Você poderia fazer isso com awk
, mas teria que escrever seu próprio analisador para lidar com aspas e vírgulas dentro dos campos.
Se você estiver executando o Debian ou similar, instale com apt install libtext-csv-perl
. Outras distros provavelmente também o possuem. Caso contrário, instale-o com cpan
.
A seguir está um exemplo bastante simples do que você pode fazer com Text::CSV
. Corra man Text::CSV
para obter detalhes.
#!/usr/bin/perl
use strict;
use Text::CSV qw(csv);
my ($filename, $search, $year) = @ARGV;
my $csv = Text::CSV->new({allow_whitespace => 1,
allow_loose_quotes => 1,
quote_space => 0,
});
open(my $in, "<", $filename) or die "couldn't open $filename: $!";
my @headers = $csv->header($in);
pop @headers; # discard last field from @headers
$csv->say(*STDOUT, \@headers); # print the headers
while (my $row = $csv->getline($in)) {
# note: perl arrays start from zero, not one. So $row->[0] is
# the first field. $row->[3] is the fourth.
if ($row->[0] =~ m/$search/i && $row->[3] == $year) {
pop @{ $row }; # discard last field (year)
$csv->say(*STDOUT, $row);
}
}
close($in);
Salve-o como, por exemplo, extract.pl
e torne-o executável com chmod +x extract.pl
- da mesma forma que faria para um script de shell.
Você não forneceu dados de entrada ou saída de amostra em sua pergunta, então tive que inventar algumas bobagens.
Dado o seguinte arquivo de entrada input.csv
,:
business,description,address,year
"ABC","sells some items","123 Somewhere Street, Somewhere, V1234",2020
"BCD Co.","sells some items","123 Somewhere Street, Somewhere, V1234",2021
"BBB Pty Ltd","sells some items","123 Somewhere Street, Somewhere, V1234",2020
"BXYZ","sells some items","123 Somewhere Street, Somewhere, V1234",2021
"CDE","sells some items","123 Somewhere Street, Somewhere, V1234",2020
"DEF","sells some items","123 Somewhere Street, Somewhere, V1234",2020
Ele produzirá a seguinte saída:
$ ./extract.pl input.csv '^b' 2021
business,description,address
BCD Co.,sells some items,"123 Somewhere Street, Somewhere, V1234"
BXYZ,sells some items,"123 Somewhere Street, Somewhere, V1234"
ou seja, todos os nomes comerciais que começam com "B" ou "b" (a correspondência de regex não diferencia maiúsculas de minúsculas) com o ano 2021. Somente os 3 primeiros campos são impressos.
Observe como a saída cita campos apenas onde é essencial (ou seja, onde há vírgulas dentro dos campos). Se você quiser que os campos que contêm espaços também sejam citados, altere quote_space => 0
para quote_space => 1
no script (ou apenas exclua essa linha, pois citar campos com espaços é o padrão para Text::CSV
)