Удаление новых символов строки между узорами

Самый простой способ сделать это:

cat test.txt | perl -pe "s/^(#.*)/\e[0;32m\1\033[0m/g || s/(aaa|bbb)/\e[1;31m\1\033[0m/g"

Здесь используется логический оператор or ||, чтобы указать perl запускать второй s/// только в том случае, если первый не выполнился. т.е. аналогично if (/#/) ... else if (/aaa|bbb/) ....

Вы можете добавить еще || s/// в конце скрипта, если это необходимо, но если вам нужно найти и раскрасить много совпадений, сделать это в виде одной строки будет слишком сложно. В таком случае перепишите все это как отдельный #! /usr/bin/perl -p, возможно, с одним s///g || на строку, и завершающей точкой с запятой вместо || в последней строке.

Например:

#! /usr/bin/perl -p

s/^(#.*)/\e[0;32m\1\033[0m/g ||
s/(aaa|bbb)/\e[1;31m\1\033[0m/g || 
s/(ccc)/\e[1;34m\1\033[0m/g ;

Обратите внимание, что такой способ означает, что в любой заданной строке будет найдено только одно совпадение, и первое совпадение победит. Таким образом, в моем примере с длинным скриптом выше, если 'aaa' или 'bbb' будут найдены на строке, то они будут окрашены, но если 'ccc' будет на той же строке, то не будет.

Наконец, похоже, что вы заново изобретаете колесо. Уже существует несколько инструментов для выделения текста цветом. Например, инструмент highlight. Он в основном используется для подсветки синтаксиса исходного кода, но может быть использован для придания цвета любому виду текста.

3
17.09.2018, 09:33
2 ответа

Если команда, которую вы показываете в своем вопросе, в основном работает (для жесткого -закодированного количества файлов ), тогда

first=1
for f in file*.gz
do
    if [ "$first" ]
    then
        gzcat "$f"
        first=
    else
        gzcat "$f"| tail -n +2
    fi
done > collection_single_file

должен работать на вас. Надеюсь, логика достаточно ясна. Просмотрите все файлы (и измените подстановочные знаки в соответствии с вашими именами файлов ). Если это первое в списке, gzcatэто, так что вы получите весь файл (включая заголовок ). В противном случае используйте tailдля удаления заголовка. После того, как вы обработаете файл, никакой другой файл не будет первым.

Это вызываетtailN −1 раз, а не один раз (, как ваш ответ ). Кроме того, мой ответ должен работать так же, как ваш ответ.

1
27.01.2020, 21:25

Вариация G -Решение Мана , в котором не используется отдельная переменная для отслеживания первого файла:

set -- file*.gz

{
    gzcat "$1"; shift

    for file do
        gzcat "$file" | sed '1d'
    done
} >combined.txt

Это распаковывает первый файл, а затем перебирает остальные, пропуская каждый через короткий sedскрипт, удаляющий первую строку. Вывод перенаправляется на combined.txt.

Команда set -- file*.gzустанавливает позиционные параметры ($1, $2и т. д., которые в совокупности представляют собой массив$@)для имен файлов, соответствующих заданному шаблону. shiftудаляет $1из массива после его распаковки. Цикл проходит по оставшимся именам файлов в массиве и также может быть записан

for file in "$@"; do
    gzcat "$file" | sed '1d'
done

{... }позволяет нам перенаправить вывод команд в файл за один раз.


Еще короче, с дополнительным предположением, что «строка заголовка» всегда начинается с символа #(, как в примере в вопросе ), и что других таких строк в данных нет.:

gzcat file*.gz | awk 'NR > 1 && /^#/ { next } 1' >combined.txt

или,

gzcat file*.gz | sed '2,${ /^#/d; }' >combined.txt

Оба они пропускают любую строку, начинающуюся с #, если она встречается во второй строке или позже в объединенном содержимом несжатых данных.

1
27.01.2020, 21:25

Теги

Похожие вопросы