每行拆分多个字段,使用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

上周五我遇到了一个问题,将文本转换为另一种格式。在那台机器上,只有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 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个文本
最后,删除包含空“第二”组的行

再次尝试使用BASH(以“script.sh inputFile.txt”的形式执行):

有趣的问题:

$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是
    sed-r's@..x..@..y..@ge'文件
    ge允许我们将匹配的零件传递给外部命令
  • .y..
    部分由
    ge
    的魔力完成。我将
    \2
    传递给另一个
    sed
    (通过
    echo
    ):
    sed“s###\\n\1#g”
    此sed将所有空格替换为
    \n+\1+空格
  • 在原始文件中,每行(结束)上都有
    \n
    ,因此步骤2(上述步骤)的结果中有空行,我们需要删除这些空行
    “/^$/d”
  • 最后,可以进行步骤1中的替换(外部sed),我们得到了结果
  • 检查
    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'