Bash команда split для разделения строки на значения, разделенные запятыми - PullRequest
1 голос
/ 26 мая 2020

У меня есть большой файл с 2000 именами хостов, и я хочу создать несколько файлов по 25 хостов на файл, но разделенных запятой, и последний , должен быть удален.

Large.txt:

host1
host2
host3
.
.
host10000

Приведенная ниже команда разделения создает несколько файлов, таких как file1, file2 ... однако хосты не разделены , и это не ожидаемый результат.

split -d -l 25 large.txt file

Ожидаемый результат:

host1,host2,host3

Ответы [ 4 ]

1 голос
/ 26 мая 2020

Вам потребуется выполнить 2 отдельные операции ... 1) split файл и 2) переформатировать файлы, созданные split.

Первый шаг уже выполнен:

split -d -l 25 large.txt file

На втором этапе давайте поработаем с результатами, которые выгружаются в первый файл командой basi c split:

$ cat file00
host1
host2
host3
...
host25

Мы хотим вывести эти строки в одна строка с запятой (,) в качестве разделителя. В этом примере я буду использовать решение awk:

$ cat file00 | awk '{ printf "%s%s", sep, $0 ; sep="," } END { print "" }'
host1,host2,host3...,host25

Где:

  • sep изначально не определено (также называется пустой строкой)
  • на каждой последующей строке, обрабатываемой awk, мы устанавливаем sep в запятую
  • printf не включает перевод строки (\n), поэтому каждый последующий printf будет добавляться к 'первому 'строка вывода
  • мы END сценарий путем печати перевода строки в конец файла

Так уж случилось, что split имеет возможность вызвать вторичный сценарий / фрагмент кода, позволяющий настраивать формат вывода (генерируется split); вариант - --filter. Следует иметь в виду несколько моментов:

  • начальный вывод из split (эффективно) передается по конвейеру как ввод для команды, указанной в опции --filter
  • это необходимо для экранирования (с помощью backsla sh) определенных символов в команде (например, двойных кавычек, знака доллара), чтобы они не интерпретировались командой split
  • опция --filter автоматически имеет доступ к текущему имени split файла с использованием переменной $FILE

Собирая все вместе, мы получаем:

$ split -d -l 25 --filter="awk '{ printf \"%s%s\", sep, \$0 ; sep=\",\" } END { print \"\" }' > \$FILE" large.txt file
$ cat file00
host1,host2,host3...,host25
1 голос
/ 26 мая 2020

Использование опции --filter в GNU split:

split -d -l 25 --filter="(perl -ne 'chomp; print \",\" if \$i++; print'; echo) > \$FILE" large.txt file
0 голосов
/ 26 мая 2020

с использованием awk:

awk '
BEGIN            { PREFIX = "file"; n = 0; }
                 { hosts = hosts sep $0; sep = ","; }
function flush() { print hosts > PREFIX n++; hosts = ""; sep = ""; }
NR % 25 == 0     { flush(); }
END              { flush(); }
' large.txt

edit: улучшена обработка разделения запятых кража из отличный ответ markp-fuso :)

0 голосов
/ 26 мая 2020

вы можете использовать нижеуказанный bash фрагмент кода

ВХОДНОЙ ФАЙЛ

~$ cat domainlist.txt
domain1.com
domain2.com
domain3.com
domain4.com
domain5.com
domain6.com
domain7.com
domain8.com

Скрипт

#!/usr/bin/env bash

FILE_NAME=domainlist.txt
LIMIT=4
OUTPUT_PREFIX=domain_
CMD="csplit ${FILE_NAME} ${LIMIT} {1} -f ${OUTPUT_PREFIX}"
eval ${CMD}
#=====#
for file in ${OUTPUT_PREFIX}*; do
    echo $file
    sed -i ':a;N;$!ba;s/\n/,/g' $file
done

ВЫХОД

./mysplit.sh 

36
48
12
domain_00
domain_01
domain_02
~$ cat domain_00
domain1.com,domain2.com,domain3.com

Измените LIMIT, префикс имени файла OUTPUT_PREFIX и входной файл в соответствии с вашими требованиями

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...