Используйте sed для переформатирования строки, дублируйте один раздел в начале других разделов в отдельных строках
Для LS_COLORS и ~/.dir_colors загрузка с фильтром (sed?) Вместо того, чтобы иметь
"pattern color" "pattern color"
... в 10 строках хотелось бы
DEF_COLOR color pattern pattern pattern...
в одной строке. Как sed переформатировать строку, чтобы я мог использовать
DEF_COLOR 31 .tar .tgz .zip .z .gz .bz .tbz .tbz
и получить необходимое количество строк в реальном формате файла конфигурации? Как это...
.tar 31
.tgz 31
.zip 31
.z 31
.gz 31
.bz 31
.tbz 31
5 ответов
Это то, что вы пытаетесь сделать?
$ cat file
DEF_COLOR 31 .tar .tgz .zip .z .gz .bz .tbz .tbz
$ awk '{for (i=3;i<=NF;i++) print $i, $2}' file
.tar 31
.tgz 31
.zip 31
.z 31
.gz 31
.bz 31
.tbz 31
.tbz 31
Если вы хотите сделать это только для строки, которая начинается с DEF_COLOR (единственная строка в примере, но, возможно, у вас есть другие), тогда:
awk '/^DEF_COLOR/{for (i=3;i<=NF;i++) print $i, $2}' file
Вышеупомянутое будет вести себя одинаково при использовании любого awk в любой оболочке в каждом блоке Unix, поэтому, если вы ищете решение, переносимое во все системы Unix, это оно.
Мне нравится sed, но мне это не нравится. (Он плохо справляется с разделителями полей)
Вот версия на Perl.
perl -lne '@f=split;print "$_ $f[1]" for @f[2..$#f]'
- разбить строку на массив
@f
- использовать
-l
чтобы получить разрыв строки на каждом отпечатке - распечатать каждый элемент в
@f
с 3-го до последнего со 2-м элементом впоследствии
Или, как указывает @tshiono, добавьте
-a
чтобы получить массив автоматически:
perl -lane 'print "$_ $F[1]" for @F[2..$#F]'
В общем
perl -p
и
perl -n
перевести Perl в режим потоковой обработки, аналогичный
sed
и
sed -n
... но с гораздо большим количеством доступных инструментов.
С участием
GNU sed
как насчет:
echo DEF_COLOR 31 .tar .tgz .zip .z .gz .bz .tbz .tbz21 .tz .zoo .7z .rz | sed 's/ /\n/g' | sed -n '
2{h;d} ;# save the 2nd line in hold space and delete pettern space
3,${G;s/\n/ /;p} ;# append hold space to pattern space; replace the 1st newline with a whitespace; then print pattern space
Вывод:
.tar 31
.tgz 31
.zip 31
.z 31
.gz 31
.bz 31
.tbz 31
.tbz21 31
.tz 31
.zoo 31
.7z 31
.rz 31
Как отмечает @stevesliva, я бы предпочел использовать другой язык для такого рода задач:)
sed '/^DEF_COLOR */{ s/// ; t x ; :x
s/\([^ ]*\) *\([^ ]*\)/\2 \1\nDEF_COLOR \1/; t ok
d
:ok ; P;D}
- Работайте только со строками DEF_COLOR, удалите их и пробелы и используйте t x;:x (nop), чтобы очистить флаг перехода.
- Затем s ///, чтобы поменять местами первые 2 слова (31 .tar -> .tar 31) для печати, но также добавить новую строку (конец печати) и снова добавить цвет DEF_COLOR, так что это все еще будет строка DEF_COLOR после \n.
DEF_COLOR 31.tar.tgz... становится.tar 31\nDEF_COLOR 31 .tgz... и если это сработало, goto ok (пропустите d в #3)(t перескакивает, если s /// сработало, но это сработало на шаге #1 тоже, поэтому t ok;:ok там, так что t здесь проверяет, только если это s /// сработало) (этот шаг уродливый, я уверен, что есть способы получше) - Если s /// не удалось (остается только цвет, без узоров), удалите все. (линия сделана)
- ok: смена шаблона / цвета сработала, поэтому P(печать до новой строки (цвет шаблона));D(удаление до новой строки) и начало заново (продолжайте укорачивать строку DEF_COLOR до тех пор, пока шаблоны не исчезнут)
Я уверен, что это можно улучшить, но это работает.
PS: Извините за ответ на мой вопрос. (и я думаю, что воспользуюсь решением perl)
Просто сделать это сценарием кажется лучшим ответом.
function EXT() { for x in "$@"; do echo ".$x $COLOR"; done; }
COLOR=31 EXT tar tgz zip z gz bz tbz tbz
Чтобы ответить на вопрос, как я его задал,
DEF_COLOR 31 .tar .tgz .zip .z .gz .bz .tbz .tbz
я мог бы использовать
function DEF_COLOR { C="$1"; shift; for x in "$@"; do echo "$x $C"; done; }