每行拆分多个字段,使用sed分隔行,保留行前缀
上周五我遇到了一个问题,将文本转换为另一种格式。在那台机器上,只有gnu sed可用,没有awk(奇怪,我知道)。我对perl一无所知。因此,我正在寻找一个sed唯一的解决方案 文件内容为:每行拆分多个字段,使用sed分隔行,保留行前缀,sed,Sed,上周五我遇到了一个问题,将文本转换为另一种格式。在那台机器上,只有gnu sed可用,没有awk(奇怪,我知道)。我对perl一无所知。因此,我正在寻找一个sed唯一的解决方案 文件内容为: a yao.com sina.com b kongu.com c polm.com unee.net 21cn.com iop.com foo.com bar.com baz.net happy2all.com d kinge.net 所需输出(应为新文件)为: 我尝试了很多,也搜索了著名的sed
a yao.com sina.com
b kongu.com
c polm.com unee.net 21cn.com iop.com foo.com bar.com baz.net happy2all.com
d kinge.net
所需输出(应为新文件)为:
我尝试了很多,也搜索了著名的sed oneliner,但我做不到。。。有人能帮我吗
cat inputFile.txt | sed -e 's/\([^\ ]*\)\(\ *\)\([^\ ]*\)\(\ *\)\([^\ ]*\)\(\ *\)\([^\ ]*\)\(\ *\)\([^\ ]*\)\(\ *\)/\1 \3\n\1 \5\n\1 \7\n\1 \9/' | grep -vE "^..$"
适用于我的Ubuntu 12.10
说明:
- 将其分为两组:带文本的组和带空字符的组
- 重复组1(带第一个字符)和偶数组(带文本)
- 目前适用于由空字符分隔的4个文本
$sed-r/(\w+\.\w+/>&/2g;:a s/^([a-z]+)(.*)>/\1\2\n\1/g;ta'文件
a姚网
新浪网
b kongu.com
c polm.com
c.unee.net
c21cn.com
c iop.com
c foo.com
c.bar.com
c baz.net
c happy2all.com
d kinge.net
编辑:
它通过使用两个替换来工作
第一个将>
放在需要展平的URL之前作为保留字符:
$sed-r的/(\w+\.\w+/>和/2g”文件
a姚网>新浪网
b kongu.com
c polm.com>unese.net>21cn.com>iop.com>foo.com>bar.com。。。
d kinge.net
第二个基本上用换行符替换了holding
(使用条件分支):
$sed-r':a s/^([a-z]+)(.*)>/\1\2\n\1/g;ta'
您可以使用
sed -r -n 's/^([a-z])\ \ ([0-9a-z.]*)\ ([0-9a-z .]*)/\1 \2\n\1 \3/p'
它将转换表单的每一行
c polm.com unee.net 21cn.com iop.com foo.com bar.com baz.net happy2all.com
进入
每次它运行时
因此,下次在上一个sed的输出上运行时,它将成为
c polm.com
c unee.net
c 21cn.com iop.com foo.com bar.com baz.net happy2all.com
等等
因此,将前一个sed的输出推送到新的sed中,最终会得到所需的格式
我知道这可能不是最佳答案,如果可能的话,我会尝试改进它。对于sed来说,这不是一件容易的工作,尤其是一行程序。然而你提到“gnu sed”。我看到了光明 gnu sed支持
s/../…/ge
,这在这种情况下非常有用:
kent$ sed -r 's@(^[a-z]+) (.*)@echo "\2"\|sed "s# #\\n\1 #g"\|sed "/^$/d"@ge' file
a yao.com
a sina.com
b kongu.com
c polm.com
c unee.net
c 21cn.com
c iop.com
c foo.com
c bar.com
c baz.net
c happy2all.com
d kinge.net
简要说明:
sed-r's@..x..@..y..@ge'文件
ge允许我们将匹配的零件传递给外部命令.y..
部分由ge
的魔力完成。我将\2
传递给另一个sed
(通过echo
):sed“s###\\n\1#g”
此sed将所有空格替换为\n+\1+空格
\n
,因此步骤2(上述步骤)的结果中有空行,我们需要删除这些空行“/^$/d”
info sed
中的s/../ge
编辑,添加了OP评论中的双空格。正如其他人所指出的,sed解决方案很棘手,所以我想我发布了一个bash dito:
#!/bin/bash
while read -a array
do
for i in ${array[@]:1}
do
echo ${array[0]} $i
done
done < input
下面是一个真正的sed-only脚本。我在下面编写了一个由sed在命令行上调用的文件,但它可以全部在命令行上键入,也可以全部输入到单独的脚本中: 将以下内容另存为sedscript(或任何您想称之为sedscript的内容)。在输出之后进行解释
:start
h
s/\(.\ \ [^ ]*\).*/\1/
t continue
d
:continue
p
x
s/\(.\ \)\ [^ ]*\(\ .*\)/\1\2/
t start
d
现在运行sed-f sedscript myfile.txt
上面的示例保存为myfile.txt,输出如下:
a yao.com
a sina.com
b kongu.com
c polm.com
c unee.net
c 21cn.com
c iop.com
c foo.com
c bar.com
c baz.net
c happy2all.com
d kinge.net
Sed有一个模式缓冲区(通常使用s/a/b/
类命令)和一个保持缓冲区。在这个脚本中,信息被来回交换到保持缓冲区,以在处理另一部分时保留行的未编辑部分
:开始
=启用跳转的标签
h
=将模式缓冲区(当前行)交换到保持缓冲区
s/\(.\\[^]*\)./\1/
=当保留缓冲区中的完整行是安全的时,去掉第一个域后的所有内容,留下第一个所需行(例如“a yao.com”)
t continue
=如果上一个命令导致替换,请跳转到“continue”标签
d
=如果我们不跳,那就意味着我们完了。删除模式缓冲区并继续文件的下一行
:继续
=上一次跳转的标签
p
=打印出模式缓冲区(例如“a yao.com”)
x
=将模式缓冲区与保持缓冲区交换(也可以使用g
简单地将保持缓冲区复制到模式缓冲区上)
s/\(.\\)\[^]*\(\.*\)/\1\2/
=完整的原始字符串现在已交换到模式缓冲区中-剥离我们刚刚处理的域(例如“yao.com”)
t start
=如果这不是最后一个域,请使用新的缩短字符串重新启动脚本
d
=如果这是最后一个域,请删除模式缓冲区并继续文件中的下一行。这可能适用于您(GNU-sed):
这里有一个单行程序(对于“一”的某些定义)可以实现这一点。它应该可以在任何sed上运行,但我只使用gnused对它进行了测试
sed ':l;s/\(^\|\n\)\([^ \n]\) \([^ \n][^ \n]*\) /\1\2 \3\
\2 /;t l'
这是\3\
后面的文字换行符
说明:
:l
制作了一个名为l
的标签tl
循环到标签l
s
命令对最初包含输入行的模式空间缓冲区进行操作。在执行s
命令之后,模式空间缓冲区包含替换的结果,包括换行符。通过循环的第二次和后续时间,a yao.com
a sina.com
b kongu.com
c polm.com
c unee.net
c 21cn.com
c iop.com
c foo.com
c bar.com
c baz.net
c happy2all.com
d kinge.net
:start
h
s/\(.\ \ [^ ]*\).*/\1/
t continue
d
:continue
p
x
s/\(.\ \)\ [^ ]*\(\ .*\)/\1\2/
t start
d
a yao.com
a sina.com
b kongu.com
c polm.com
c unee.net
c 21cn.com
c iop.com
c foo.com
c bar.com
c baz.net
c happy2all.com
d kinge.net
sed -r 's/^((\S+\s+)\S+)\s+/\1\n\2/;P;D' file
sed ':l;s/\(^\|\n\)\([^ \n]\) \([^ \n][^ \n]*\) /\1\2 \3\
\2 /;t l'