
#nombre de archivo como $1
#nombre comercial como $2
#actualizado en el año $3 #Puede coincidir con cualquier coma dentro de los valores de comillas siempre que esté antes de la V coincidente del código postal. Todos comienzan con V.
./script6_1.sh bcindigenousbusinesslistings.csv "B.*" 2021
Para encontrar todos los negocios que comienzan con B actualizados en 2020 o posterior.
#El primer sed es poner desde la línea 2 hasta la última línea #El segundo sed: Al principio de la línea, puede coincidir con cualquier patrón hasta la V (código postal), luego se detendrá $3 coincidirá con cualquier número que tiene un patrón de 20 (1 a 3) y (0-9) para el último dígito
*sed -n '2,$p' $1 | sed -e 's/^\('$2'[^,]*,[^,]*,[^,]*,.*[^V],\)\('$3'202[0-9]\)/\1\2/'*
El punto principal es extraer 3 columnas, cada una separada por comas. Negocio, Descripción, Dirección. La última columna es Año de actualización. Dentro de la descripción de la columna, puede haber más comas separadas.
Tengo un error en esto ya que simplemente imprime toda la línea, sin extraer el patrón coincidente.
Respuesta1
Si desea trabajar con columnas dentro de una línea en lugar de con toda la línea, entonces awk
o perl
sería una herramienta mucho mejor para este trabajo que sed
.
Y, dado que necesita lidiar con campos entre comillas (con comas dentro de ellos), sería mejor que los use perl
porque tiene unTexto::CSVmódulo que analiza archivos CSV como ese. Podrías hacerlo con awk
, pero tendrías que escribir tu propio analizador para manejar comillas y comas dentro de los campos.
Si está ejecutando Debian o similar, instálelo con apt install libtext-csv-perl
. Probablemente otras distribuciones también lo tengan empaquetado. De lo contrario, instálelo con cpan
.
El siguiente es un ejemplo bastante simple de lo que puede hacer con Text::CSV
. Corre man Text::CSV
para obtener más detalles.
#!/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);
Guarde esto como, por ejemplo, extract.pl
y hágalo ejecutable con chmod +x extract.pl
- igual que lo haría con un script de shell.
No has dado entrada o salida de muestra en tu pregunta, así que tuve que inventar algunas tonterías.
Dado el siguiente archivo 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
Producirá el siguiente resultado:
$ ./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"
es decir, todos los nombres comerciales que comienzan con "B" o "b" (la coincidencia de expresiones regulares no distingue entre mayúsculas y minúsculas) con el año 2021. Solo se imprimen los primeros 3 campos.
Observe cómo el resultado ha citado campos sólo donde es esencial (es decir, donde hay comas dentro de los campos). Si desea que los campos que contienen espacios también se entrecomillan, cambie quote_space => 0
a quote_space => 1
en el script (o simplemente elimine esa línea ya que citar campos con espacios es la opción predeterminada para Text::CSV
)