使用 sed 重新格式化行,将一个部分复制到单独行上其他部分的开头
Use sed to reformat line, duplicate one section onto the begining of other sections on seperate lines
对于 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
我喜欢 sed,但我不喜欢它。 (它不能很好地处理字段分隔符)
这是 perl 版本。
perl -lne '@f=split;print "$_ $f[1]" for @f[2..$#f]'
- 将行分割成数组
@f
- 使用
-l
在每次打印时换行
- 从第 3 项到最后一项打印
@f
中的每一项,然后是第 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 评论的那样,我更愿意使用其他语言来完成此类任务:)
这是你想要做的吗?
$ cat file
DEF_COLOR 31 .tar .tgz .zip .z .gz .bz .tbz .tbz
$ awk '{for (i=3;i<=NF;i++) print $i, }' 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, }' file
在每个 Unix 机器上使用任何 shell 中的任何 awk 上面的行为都是一样的,所以如果你正在寻找一个可以跨所有 Unix 系统移植的解决方案,这就是它。
sed '/^DEF_COLOR */{ s/// ; t x ; :x
s/\([^ ]*\) *\([^ ]*\)/ \nDEF_COLOR /; t ok
d
:ok ; P;D}
- 只处理 DEF_COLOR 行,删除那个和空格,然后使用 t x ; :x (nop) 清除跳转标志。
- 然后s///交换前2个字(31 .tar -> .tar 31)进行打印,还要加一个换行符(结束打印)并加上DEF_COLOR 颜色,所以它仍然是 \n 之后的 DEF_COLOR 行。
DEF_COLOR 31 .tar .tgz... 变为 .tar 31\nDEF_COLOR 31 .tgz... 如果有效则转到 ok(跳过 d in #3)(t jumps if s/// worked,但它在步骤 #1 中也有效,这就是为什么 t ok;:ok 在那里,所以这里的 t 仅测试这个 s/// 是否有效)(这一步是丑陋,我相信有更好的方法)
- 如果 s/// 失败(只剩下颜色,没有图案),全部删除。 (线完成)
- ok:交换 pattern/color 有效,所以 P(print to newline(pattern color));D(delete to newline) 和 start 再次(继续缩短 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=""; shift; for x in "$@"; do echo "$x $C"; done; }
对于 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
我喜欢 sed,但我不喜欢它。 (它不能很好地处理字段分隔符)
这是 perl 版本。
perl -lne '@f=split;print "$_ $f[1]" for @f[2..$#f]'
- 将行分割成数组
@f
- 使用
-l
在每次打印时换行 - 从第 3 项到最后一项打印
@f
中的每一项,然后是第 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 评论的那样,我更愿意使用其他语言来完成此类任务:)
这是你想要做的吗?
$ cat file
DEF_COLOR 31 .tar .tgz .zip .z .gz .bz .tbz .tbz
$ awk '{for (i=3;i<=NF;i++) print $i, }' 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, }' file
在每个 Unix 机器上使用任何 shell 中的任何 awk 上面的行为都是一样的,所以如果你正在寻找一个可以跨所有 Unix 系统移植的解决方案,这就是它。
sed '/^DEF_COLOR */{ s/// ; t x ; :x
s/\([^ ]*\) *\([^ ]*\)/ \nDEF_COLOR /; t ok
d
:ok ; P;D}
- 只处理 DEF_COLOR 行,删除那个和空格,然后使用 t x ; :x (nop) 清除跳转标志。
- 然后s///交换前2个字(31 .tar -> .tar 31)进行打印,还要加一个换行符(结束打印)并加上DEF_COLOR 颜色,所以它仍然是 \n 之后的 DEF_COLOR 行。
DEF_COLOR 31 .tar .tgz... 变为 .tar 31\nDEF_COLOR 31 .tgz... 如果有效则转到 ok(跳过 d in #3)(t jumps if s/// worked,但它在步骤 #1 中也有效,这就是为什么 t ok;:ok 在那里,所以这里的 t 仅测试这个 s/// 是否有效)(这一步是丑陋,我相信有更好的方法) - 如果 s/// 失败(只剩下颜色,没有图案),全部删除。 (线完成)
- ok:交换 pattern/color 有效,所以 P(print to newline(pattern color));D(delete to newline) 和 start 再次(继续缩短 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=""; shift; for x in "$@"; do echo "$x $C"; done; }