Unix -Связанные с командой Sed

В1. Подстановка команд (обратные кавычки )использует подоболочку, а в zsh состояние ГСЧ подоболочки не обновляется. Поскольку вы неоднократно создаете новую подоболочку без использования $RANDOMв родительском элементе, вы получаете одно и то же значение в каждой подоболочке. См.:
https://stackoverflow.com/questions/32577117/references-to-random-in-subshells-all-returning-identical-values
https://superuser.com/questions/1210435/different-behavior-of-in-zsh-and-bash-functions

Вам не нужны подстановка и эхо команды -, и вам также не нужна $((..)), потому что индекс массива уже оценивается как арифметическое выражение, но вам нужно +1, потому что массивы zsh 1 -origin (вам повезло, что вы не попали 0):

 out=$out${charlists[ $RANDOM % ${#charlists[*]} + 1 ]}

Помимо :, даже если вам нужно echoв подстановке команд, вам не нужно -n, потому что подстановка команд сама по себе удаляет любую конечную новую строку (с )из захваченных и замененных данных.

В2. bash расширяет фигурные скобки -перед расширением параметра -(и командной и арифметической подстановкой/расширением ), но zsh (и ksh )делают это после. Вы можете использовать for i in $(seq 1 $1)или гадкий, но встроенныйfor i in $(eval "echo {1..$n}")

-2
19.06.2021, 05:24
1 ответ

Если вы хотите работать со столбцами внутри строки, а не со всей строкой, то awkили perlбудут гораздо лучшим инструментом для этой работы, чем sed.

И, поскольку вам нужно справиться с полями в кавычках (с запятыми внутри них ), вам лучше использовать perl, потому что у него есть модуль Text ::CSV который анализирует файлы CSV таким образом. Вы можете сделать это с помощью awk, но вам придется написать собственный синтаксический анализатор для работы с кавычками и запятыми внутри полей.

Если вы используете Debian или аналогичную систему, установите ее с помощью apt install libtext-csv-perl. Другие дистрибутивы, вероятно, тоже упакованы. В противном случае установите его с cpan.

Ниже приведен довольно простой пример того, что вы можете сделать с Text::CSV. Запустите man Text::CSVдля получения подробной информации.

#!/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);

Сохраните это как, например, extract.plи сделайте его исполняемым с помощьюchmod +x extract.pl-так же, как для сценария оболочки.

В своем вопросе вы не дали пример ввода или вывода, так что мне пришлось придумать какую-то ерунду.

Учитывая следующий входной файл,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

Будет получен следующий результат:

$./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"

т. е. все названия компаний, начинающиеся с «B» или «b» (соответствие регулярному выражению не зависит от регистра -нечувствительно к регистру )с годом 2021. Печатаются только первые 3 поля.

Обратите внимание, что выходные данные заключают в кавычки поля только там, где это необходимо (т. е. там, где внутри полей есть запятые ). Если вы хотите, чтобы поля, содержащие пробелы, также были заключены в кавычки, измените quote_space => 0на quote_space => 1в скрипте (или просто удалите эту строку, поскольку цитирование полей с пробелами является значением по умолчанию дляText::CSV)

0
28.07.2021, 11:23

Теги

Похожие вопросы