Сплит: как разделить на разные проценты?

14

Как разделить текстовый файл на 70% и 30% с помощью команды split?

aneuryzm
источник
Вы намерены использовать команду split? Если нет, то вы можете легко сделать это с помощью простых текстовых манипуляций, конечно, используя perl или python. Пока файл не слишком неправильный, считайте его в память как строку, а затем разбейте строку. Если файл слишком большой, требуется больше работы.
Фахим Митха
@Faheem Mitha Файл размером 64 МБ. Мне нравится идея использовать split, потому что это быстрее, чем написание кода. Мне было интересно, если я укажу количество строк, соответствующее 70% файла, я получу большой файл и маленький файл. Разве это не должно работать?
aneuryzm
И да .. это сработало .. Должен ли я удалить вопрос?
aneuryzm
До вас, но не обязательно.
Фахим Митха
Пожалуйста, поделитесь своим ответом. ( meta.stackexchange.com/questions/12513/… )
собачья будка

Ответы:

13

Команды ниже будут работать для процентов выше 50% (если вы хотите разделить только на два файла), быстрый и грязный подход.

1) разделить 70% на основе линий

split -l $[ $(wc -l filename|cut -d" " -f1) * 70 / 100 ] filename 

2) разделить 70% на основе байтов

split -b $[ $(wc -c filename|cut -d" " -f1) * 70 / 100 ] filename
forcefsck
источник
1
В MacOSX wc иногда возвращает количество строк с пробелом перед ним, что нарушает этот скрипт. Первый трубопровод к xargs удалит эти пробелы и заставит все снова работать: split -l $[ $(wc -l filename | xargs | cut -d" " -f1) * 70 / 100 ] filename
Эмиль Стенстрём,
4

Вы можете использовать csplitдля разделения на две части (используя любой процент), например, первая часть - первые 20% строк, вторая часть - оставшиеся 80% строк:

csplit infile $(( $(wc -l < infile) * 2 / 10 + 1))

$(wc -l < infile): общее количество строк
2 / 10: процент
+1: добавить одну строку, потому что csplitразделяетup to but not including line N

Вы можете разделить только на основе строк, хотя.
В основном, если у вас есть номер строки, $(( $(wc -l < file) * 2 / 10))вы можете использовать любой инструмент, ориентированный на строки:

sed 1,$(( $(wc -l < infile) * 2 / 10))'{
w 20-infile
d
}' infile > 80-infile

или даже круче

{ head -n$(( $(wc -l < infile) * 2 / 10)) > 20-infile; cat > 80-infile; } <infile

хотя некоторые из headних глупы и не соответствуют стандартам, так что это не будет работать на всех установках ...

don_crissti
источник
2
{   BS=$(($(wc -c <file) * $P / 100))
    dd count=1 bs="$BS" >file1; cat
} <file >file2 2>/dev/null

... должен работать в этом простом случае, потому что вы делитесь только один раз - и, вероятно split, это немного излишне. До тех пор , пока файл является доступным для поиска, ddбудет делать только один read()ON <stdin, и поэтому catостались начать его read()в любом пункте ddоставляет.

Если файл большой, то он count=1 bs=$big_ol_numможет стать немного громоздким, и его можно заблокировать с помощью некоторой дополнительной - но простой - математики оболочки.

Не-вход доступного для поиска - как из трубы - может привести к перекосу dd«результаты с, хотя это может быть обработано , а также ж / ГНУ dd» ы iflag=fullblock.

mikeserv
источник
0

Следующий код использует headи tailработает с любым соотношением (в данном случае от 40 до 60):

export FILE_NAME=train.vw
head -n $[ $(wc -l ${FILE_NAME}|cut -d" " -f1) * 40 / 100 ] ${FILE_NAME} > train_40.vw
tail -n +$[ ($(wc -l ${FILE_NAME}|cut -d" " -f1) * 40 / 100) + 1 ] ${FILE_NAME} > train_60.vw
Александр никитин
источник