Разделить на строки и взять выкройку в файл

У меня есть много файлов .txt, которые выглядят так:

файл1.txt

header
1_fff_aaa 1_rrr_aaa 1_ggg_aaa ...

файл2.txt

header
1_ttt_aaa 1_iii_aaa 1_lll_aaa ...

Я хотел бы удалить заголовок и разделить строку второй строки на несколько строк после пробела и использовать шаблон между символом _:

Выход:

file1_v1.txt

fff
rrr
ggg

file2_v1.txt

ttt
iii
lll

Я хотел бы использовать команды Unix, такие как sed

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
58
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Что-то вроде того:

Программа: split.awk

NR == 1 {
    # ignore first header line
    next
}
{
    i=1
    while (i <= NF) {
        gsub(/^[^_]*_/, "", $i)
        gsub(/_[^_]*$/, "", $i)
        print $i
        i++
    }
}

Выполнено так:

awk -f split.awk file1.txt > file1_v1.txt

Чтобы выполнить его для многих файлов:

for f in file*.txt; do echo "$f"; awk -f split.awk "$f" > "${f%.txt}_v1.txt" ; done

ОБНОВЛЯТЬ

Вы также можете использовать sed и tr:

sed -n '2,$p' file1.txt | tr " " "\n" | sed 's/^[^_]*_\(.*\)_[^_]*$/\1/'
NR == 1 { next } { foo } = NR > 1 { foo }. Вам не нужен gsub(), когда регулярное выражение привязано к началу или концу строки, достаточно sub(), поскольку оно может соответствовать только один раз. Однако вы могли бы использовать gsub(/^[^_]*_|_[^_]*$/,"",$i) вместо двух отдельных sub() в POSIX awk. i=1; while (i <= NF) { foo; i++ } чаще пишется for (i=1; i<=NF; i++) { foo }.
Ed Morton 03.03.2024 22:55

Это может сработать для вас (GNU sed):

sed -i '1d;s/\s\+/\n/g;s/^[^_]*_//mg;s/_.*//mg' file1 file2 file3 ...

Используйте параметр командной строки -i для замены inline.

Удалите первую строку каждого файла (удалите заголовок).

Замените пробелы на новые строки. Это преобразует каждый токен в отдельную строку.

Удалите первую часть строки до первого _ включительно для всех строк в пространстве шаблона.

Удалить от первого _ до конца строки, оставив результат.

Н.Б. Опцию -i можно заменить опцией -s, если пользователю требуется вывод на стандартный вывод только одного или нескольких файлов. Также обратите внимание на флаг m в последних двух командах замены, который меняет обычную замену, чтобы использовать многострочные шаблоны.

Чтобы изменить имена выходных файлов, используйте GNU Parallel:

parallel --plus "sed '1d;y/ /\n/;s/^[^_]*_//mg;s/_.*//mg' {} > {.}_v1.{+.}" ::: file1.txt file2.txt ...

Обычно я бы не стал отвечать на вопрос, на который ФП не предпринял никаких попыток решить свою проблему самостоятельно, но поскольку уже есть несколько ответов...

Используя любой awk:

$ cat tst.awk
BEGIN { FS = "_" }
FNR == 1 {
    close(out)
    out = FILENAME
    sub(/\.txt$/,"_v1&",out)
    next
}
{
    for ( i=2; i<=NF; i+=2 ) {
        print $i > out
    }
}

$ awk -f tst.awk file{1,2}.txt

$ head file{1,2}_v1.txt
==> file1_v1.txt <==
fff
rrr
ggg

==> file2_v1.txt <==
ttt
iii
lll

Другие вопросы по теме

Проблемы с работой со столбцами, изменением их формата
Замена строки с помощью sed
Использование sed для замены шаблона между фигурными скобками, где строка непосредственно перед открывающей фигурной скобкой содержит известное слово
Замените после поиска строку переменной (содержащей косую черту) в sed/awk
Bash: как извлечь родительский каталог из 3 файлов одновременно
AWK разделяет строки с заглавными и непрописными буквами точкой с запятой, если точка с запятой отсутствует
Sed для удаления строк с шаблоном, заканчивающихся нечетной цифрой
RegEx для анализа имени пакета, версии пакета (включая выпуск) для пакетов Fedora/Red Hat
Sed – почему '[.]' совпадает с началом и концом строки?
Как выбрать строки между двумя одинаковыми шаблонами маркеров, которые могут встречаться несколько раз с помощью awk/perl или любого другого инструмента командной строки