组合 sed 语句

组合 sed 语句

假设我的输入文件如下所示:

ID1
1    5
6    8
ID2
1    4
5    7

我正在尝试制定一个可以结合这些操作的循环:

  • 如果该行以字母开头:在字段后面保留 '\ n'

  • 如果该行以数字开头:将每个 '\t' 和 '\n' 替换为逗号 ( sed 's / \ t /, / g; s / \ n /, / g '),除非下一行以字母 ( sed 's / \ t /, / g')开头

预期输出:

ID1     
1, 5, 6, 8
ID2     
1, 4, 5, 7

答案1

sed '/^[0-9]/{:a;s/[\t\n ]\+/,/g;N;/\n[A-Z]/!ba;}'

会做的事情。

解释:

/^[0-9]/将仅匹配以数字开头的行并向其应用命令组

{}申请的命令组

{:a;s/[\t\n ]\+/,/g;N;/\n[A-Z]/!ba;}将逐行循环读取并将所有空格、制表符和换行符替换为逗号,直到以字母开头的行。

答案2

您应该能够按如下方式实现:如果当前行以数字开头,则将下一行追加到模式空间中,然后用逗号空格替换空格、制表符和换行符序列:

$ sed '/^[0-9]/{N;s/[ \t\n]\+/, /g}' file
ID1
1, 5, 6, 8
ID2
1, 4, 5, 7

答案3

我会选择awk,它提供了更多的控制并概括了问题:

awk 'BEGIN{FS="\t"; OFS=","}
      /^[^A-Z]/ {for (i=1; i<=NF; i++) {if (!a) a=$i; else a=a OFS $i} next}
      {if (a) print a; a=""; print}
     END{print a}'

解释

  • BEGIN{FS="\t"; OFS=","}将输入字段分隔符设置为制表符,将输出字段分隔符设置为逗号。
  • /^[^A-Z]/ {for (i=1; i<=NF; i++) {if (!a) a=$i; else a=a OFS $i} next}在不以大写字母开头的行中,将值存储在变量中a
  • {if (a) print a; a=""; print}在其余情况下(即以大写字母开头的行),将存储的值与当前行一起打印。
  • END{print a}处理整个文件后,使用最后一个块中的值打印最后存储的变量。

查看输出:

$ awk 'BEGIN{FS="\t"; OFS=","}/^[^A-Z]/ {for (i=1; i<=NF; i++) {if (!a) a=$i; else a=a OFS $i} next} {if (a) print a; a=""; print} END{print a}' file
ID1
1,5,6,8
ID2
1,4,5,7

在 sed 中,请记住您始终可以使用-e选项来组合命令。

答案4

tr -s '\t\nI' '  \n' <<\DATA |\
sed 's/^/I/;s/  */\n/;s/  *[0-9]/,&/g'
ID1
1    5
6    8
ID2
1    4
5    7
DATA

输出

ID1
1, 5, 6, 8
ID2
1, 4, 5, 7    
  • 首先tr将所有制表符和换行符转换为空格所有资本都换行。它还会挤压重复次数。这使得事情变得非常简单,因为此时它传递给sed如下所示的输入:

    ^D [num] [num] [num] [num] [num] ... [num] $

  • 接下来sed放置返回,用换行符替换该行的第一个空格,清除所有尾随空格,然后...

  • 在该行剩余的每个空格前面添加一个逗号,就完成了。

相关内容