Разбить текстовый файл на блоки и сохранить

#linux #bash #for-loop #awk #split

#linux #bash #for-цикл #awk #разделить

Вопрос:

У меня есть большой текстовый файл, сохраненный с именем test.txt.Теперь я хочу разделить большие текстовые файлы на блоки по ... символу и хочу сохранить имя так же, как и то, что есть после /home/niu/ . (В приведенном ниже примере данных мне нужны блоки данных, которые нужно сохранить 20190630_073410_1.5_29_PCK.txt для первого блока, 20180630_073410_1.5_29_PCK.txt для второго блока и 20190830_093410_1.5_29_PCK.txt для третьего блока.

Таким образом, я попробовал приведенный ниже код:

 #!/bin/sh
for file in 'test.txt'
do
split -l '...'
done
  

Это не работает: я надеюсь, что кто-нибудь мне поможет.Спасибо.

Мои данные, сохраненные в test.txt приведено ниже:

     ...........................................................................................................   
    /home/niu/20190630_073410_1.5_29_PCK.txt 470.2359935984357 41573823894247.63 53.46648291467124 216 1 0.1
    /home/niu/20190630_073410_1.5_29_PCK.txt 13.124782961287574 219608788311302.7 53.46425102814092 219 1 0.6
    /home/niu/20190630_073410_1.5_29_PCK.txt 4.092419925137149 12174862157739.746 53.44206693334351 291 1 1.1
    ...........................................................................................................
    /home/niu/20180630_073410_1.5_29_PCK.txt 2.241494955966288 363350265475740.4 53.36874778729164 219 1 0.1
    /home/niu/20180630_073410_1.5_29_PCK.txt 1.6671382966847936 282579486756.3921 53.234249504389624 218 1 2.1
    /home/niu/20180630_073410_1.5_29_PCK.txt 1.4410832347641427 17729080367.579777 53.06935945567802 216 1 2.6
    ...........................................................................................................
    /home/niu/20190830_093410_1.5_29_PCK.txt 1.2367527642969733 5141.577700615736 52.776493933960644 127 0 3.6
    /home/niu/20190830_093410_1.5_29_PCK.txt 1.171644866817557 3279.978138771641 52.65760209064783 135 0 4.1
    /home/niu/20190830_093410_1.5_29_PCK.txt 1.120249969361367 2441.45977994814 52.54882982584634 105 0 4.6
  

Комментарии:

1. упорядочены ли строки в файле по первому столбцу (т.Е. По имени каталога / файла)? у вас действительно есть строки ................. в файле? все ли строки начинаются с имени каталога / файла и имеют одинаковый формат <directory>/*.*.txt ? учитывая примерный набор входных данных, пожалуйста, обновите свой вопрос желаемым результатом (например, 3x новых файлов? и отобразить содержимое каждого файла)

Ответ №1:

 awk '/.../{close(out); next} {split($1, a, "/"); out=a[4]; print > out}' file
  

Вы можете использовать этот awk. Я предположил, что dots ( ... ) существует только в разделяющих строках, также все остальные строки начинаются с /home/niu/filename.txt , откуда мы получаем выходное имя файла. Если это не так, пожалуйста, обновите вопрос.

Ответ №2:

вы можете использовать csplit следующим образом:

 csplit test.txt '/^./' {*}
  

Ответ №3:

Не могли бы вы, пожалуйста, попробовать следующее, написанное и протестированное с показанными примерами в GNU awk .

 awk -F'[ /]' '
!NF || /^. /{
  next
}
out_file!=$4{
  close(out_file)
  out_file=$4
}
{
  print >> (out_file)
}' Input_file
  

Объяснение: Добавление подробного объяснения выше.

 awk -F'[ /]' '             ##Starting awk program from here and setting space and / for all lines.
!NF || /^. /{             ##Checking condition if number of fields is NULL OR line starting from dot then do following.
  next                     ##next will skip all further statements from here.
}
out_file!=$4{              ##Checking condition if prev is NOT equal to out_file then do following.
  close(out_file)          ##Closing file in back end to avoid too many files opened error here.
  out_file=$4              ##Setting out_file as 4th field here.
}
{
  print >> (out_file)      ##Printing current line to out_file output file.
}' Input_file              ##Mentioning Input_file name here.
  

РЕДАКТИРОВАТЬ: согласно OP, могут быть строки, начинающиеся с пробелов, поэтому в этом случае попробуйте.

 awk -F'/' '
!NF || /^./{
  next
}
{
  split($4,arr," ")
}
out_file!=arr[1]{
  close(out_file)
  out_file=arr[1]
}
{
  print >> (out_file)
}' Input_file