Невозможно разделить действительный и недействительный файл в теме сценария unix

Чтобы выполнить сортировку по двум полям, необходимо сообщить sort, что это такое и как их сортировать; например:

sort -k1,1nr -k2b < input

сортирует по полю 1(-k1,1)численно в обратном (убывающем )порядке; для строк, где поле 1 равно, вторичная сортировка по остальной части строки(-k2)обычно (лексически )без начальных пробелов (интервал между первым и вторым полем )в ключе сортировки(b). Вывод на вашем примере ввода:

  4 alice
  4 bottle
  4 came
  4 sure
  4 window
  3 began
  3 little
  3 moment
  3 rabbit
  3 thing
  3 till
  2 went
  2 wonder
  2 wont
0
08.05.2020, 15:15
2 ответа

В качестве альтернативы, используя grepи предполагая, что ни sed, ни grepне могут быть использованы и что у вас есть тысячи файлов, каждый из которых содержит тысяч строк, так что вы хотите проверить только самую первую строку каждого, а не grepпинговать их полностью.....

Возьмите все первые строки (с именем файла )и закиньте их в файл

head -n1 *.csv > list

Каждая запись имеет одну строку контекста (имя файла ), первую строку и пустую строку после, например

==> a.csv <==
1234567,11111111111111111111111111111111111111111111111111

==> b.csv <==
1234567845610111211111111111111111111111111

Вы знаете, что шаблон для согласования строк — это ^[0-9.]+,[0-9.]+$, поэтому вы можете

grep -E -B1 "^[0-9]+,[0-9]+$" list | grep -oP "(?<= )[^, <]+" > ok.list

Первый grepизвлекает совпадения из listс одной строкой контекста перед-B1(именем файла, содержащим совпадение ), а второй удаляет имена файлов и выгружает их в нужный файлok.list

Наконец, вы можете использовать ok.listдля фильтрации

ls *.csv | grep -Fvxf ok.list > banjaxed.list

Где вы просто используете grepдля фильтрации файлов в ok.listиз файлов из lsс фиксированными строками (не регулярное выражение )'-F', только точные совпадения -xиспользуя файлы -fкак список шаблонов для сопоставления и, конечно же, инвертируя -vсовпадение, окончательно перенаправляя отфильтрованный список наbanjaxed.list

Если это не стоит хоть чего-то, то я пакую свои игрушки.

0
28.04.2021, 23:16

Если я правильно понимаю, что вы хотите удалить любой файл, содержащий любую строку, в которой верно любое из следующих утверждений:

  1. Поле 1 пусто!$1
  2. Поле 2 пусто!$2
  3. Нет 2 полейNF!=2

Тогда

awk -F',' 'BEGINFILE{ok=1}!$1||!$2||NF!=2{ok=0; nextfile}ENDFILE{if (ok) print FILENAME}' *.csv

Который просто устанавливает флаг ok=1, а затем выполняет цикл по каждой строке до тех пор, пока любое из вышеуказанных условий не будет истинным, и, как только он находит «плохую» строку, делает файл недействительным с помощью ok=0и пропускает до конца файл без разбора дополнительных строк nextfile.

В конце каждого файла ENDFILEон печатает FILENAMEтолько тогда, когда if (ok)не равно -нулю

Таким образом, чтобы отменить совпадение, просто инвертируйте последний тест на if (!ok)для печати

awk -F',' 'BEGINFILE{ok=1}!$1||!$2||NF!=2{ok=0; nextfile}ENDFILE{if (!ok) print FILENAME}' *.csv

Редактировать

Я не могу воспроизвести сбой вывода на своемgawk(см. ниже, включая перенаправление имен файлов в xxx.file)

bash --version
GNU bash, version 5.0.16(1)-release (x86_64-pc-linux-gnu)

awk --version
GNU Awk 5.1.0, API: 3.0 (GNU MPFR 4.0.2, GNU MP 6.2.0)

tail -n +1 *.csv; 
  awk -F',' 'BEGINFILE{ok=1}
    !$1||!$2||NF!=2{ok=0; nextfile}
  ENDFILE{gzout=(ok)?"ok":"banjaxed"; print FILENAME > gzout".files"}' *.csv ; 
tail -n +1 *.files

==> a.csv <==
1234567,11111111111111111111111111111111111111111111111111

==> b.csv <==
1234567845610111211111111111111111111111111

==> c.csv <==
111111,22222222,3333333,,,44444444444444444444

==> banjaxed.files <==
b.csv
c.csv

==> ok.files <==
a.csv

Ограничения длины отдельных полей (1024)не должны быть проблемой для awk, если только вы не превысите ограничение в 3000 символов, и в этом случае ни awk, ни sedне кажутся инструменты для работы.

0
28.04.2021, 23:16

Теги

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