#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 «с», но вместо огранки, цвета, четкости и карата речь идет о целостности, сцеплении, лаконичности и соответствии.