Как извлечь файлы из объединенного файла

#awk #extraction

#awk #извлечь

Вопрос:

Я хочу разделить объединенный файл на два файла. Файл:

 file.dat

i =100
1 2 3
i =1
-1 -2 -3
i =101
1 2 3
i =102
1 2 3
i =103
1 2 3
i =2
-1 -2 -3 
....
  

Смешанные индексы являются

 1,2,3,4, ...,99 
  

и

 100, 101, 102, 103,...,200.
  

Индексы отображаются поочередно, но правила нет.
Данные

 1 2 3 
  

и

 -1 -2 -3 
  

просто обозначайте блок данных на каждом шаге.

Не могли бы вы предложить идею разделения объединенного файла на два файла с учетом индексов?

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

1. вы хотите отсортировать данные по индексу? (это проблема с многострочной записью)

2. Спасибо за ответ! Я хочу разделить файл на два файла. Каждый из них имеет индексную строку «i = ..».

3. Каков ожидаемый результат?

4. @Jidder Ожидается, что результат будет i=100 n 1 2 3 n i=101 n 1 2 3 ... и i=1 n -1 -2 -3 n i=2 n -1 -2 -3 ... @Mark Setchell Ответ Марка Сетчелла напрямую не включает i=.. строку. Спасибо за ваш ответ.

5. Просто используйте awk -F= '/^i/{x=$2<100?"a.txt":"b.txt"}{print>x}' file

Ответ №1:

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

 # separate.awk

{
  if ($1 == "i")
  {
    split($2,a,"=");
    i = a[2];
  }

  if (i < 100)
    print > "1-99.dat";
  else
    print > "100-200.dat"
}
  

 $ awk -f separate.awk file.dat

$ cat 1-99.dat
i =1
-1 -2 -3
i =2
-1 -2 -3 

$ cat 100-200.dat
i =100
1 2 3
i =101
1 2 3
i =102
1 2 3
i =103
1 2 3
  

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

1. для этого вывода вы можете буквально просто использовать awk '{f="1-99.dat"}/1 2 3/{f="100-200.dat"}{print >f}' file

2. Я предполагаю, что не все реальные блоки данных одинаковы и содержат что-то более интересное, чем «1 2 3».

3. @Pontus Это правда, что 1 2 3 означает нечто большее. Что, если мы хотим сохранить i=** строку перед каждым блоком? Я обнаружил, что невозможно добавить его перед каждым блоком? Спасибо.

4. @jiadong обновил код, чтобы включить заголовки «i =**» в выходные файлы. Я просто удалил блок «else», чтобы все строки были записаны в выходные файлы.

Ответ №2:

Это awk должно сделать это за вас:

 awk -F= '/=/{f="a.txt";if($2>99)f="b.txt";next} {print >f}' file.dat
  

Сначала он устанавливает разделитель полей в = . Затем проверяется, содержит ли строка знак равенства, и если да, то пришло время установить имя выходного файла в любое «a.txt » или «b.txt » в зависимости от числа после знака равенства. Затем при последующих записях мы просто записываем в файл, который мы выбрали последним.

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

1. Почему вы изменили имена файлов только для того, чтобы сделать ваш код короче?

2. @Jidder Да? Я не видел никаких спецификаций того, какими должны быть имена файлов — я просто выдумал их! Я демонстрировал technique , а не предоставлял независимо проверенное решение с контролем качества 🙂

3. Да, я прочитал другой ответ и подумал, что это имена файлов, упс, я виноват: (

4. На самом деле, вы могли бы сделать это еще короче! awk -F= '/=/{f=$2>99?"b.txt":"a.txt";next}{print>f}' file.dat

5. @Pontus правильно. желательным качеством программного обеспечения является лаконичность, а не краткость сама по себе. Программное обеспечение подобно бриллианту в том смысле, что необходимо учитывать 4 «с», но вместо огранки, цвета, четкости и карата речь идет о целостности, сцеплении, лаконичности и соответствии.