Спліт: як розділити на різні відсотки?


14

Як можна розділити текстовий файл на 70% та 30% за допомогою команди split?


Чи ви готові використовувати команду split? Якщо ні, ви можете легко зробити це за допомогою прямого тексту маніпуляції, звичайно, використовуючи perl або python. Поки файл не надто помиляється, читайте його в пам'яті як рядок, а потім розділіть рядок. Якщо файл занадто великий, знадобиться більше роботи.
Faheem Mitha

@Faheem Mitha Файл становить 64 Мб. Мені подобається ідея використовувати спліт, тому що це швидше, ніж писати код. Мені зараз було цікаво, якщо я вказую кількість рядків, що відповідають 70% файлу, я отримую великий файл і невеликий файл. Чи не повинно це працювати?
аневризм

І так .. спрацювало .. Чи потрібно видалити питання?
аневризм

За вами, але не потрібно.
Faheem Mitha

Будь ласка, поділіться своєю відповіддю. ( meta.stackexchange.com/questions/12513/… )
dogbane

Відповіді:


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

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з них німі і не відповідають стандартам, тому це не працюватиме у всіх налаштуваннях ...


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залишає.

Якщо файл великий, то a count=1 bs=$big_ol_numможе отримати трохи громіздкого, і його можна заблокувати за допомогою додаткової - але простий математики оболонки.

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


0

Наступний код використовує headта tailпрацює з будь-яким співвідношенням (40 у цьому випадку 40):

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.