将新行转换为由空行分隔的文本块中的空白

时间:2015-04-09 23:42:59

标签: unix awk sed

我有一个文件如下。 数据块以区域开头,在一行线之后总是有一个水平的空格,一个空行。

foo.txt的

zone name Z_ZEBRA_TIGER vsan 900
* fcid 0x801e00 [device-alias TEST]
* fcid 0x3d8b40 [device-alias TIGER1]
* fcid 0x3d8bc0 [device-alias TIGER2]
* fcid 0x3d8b60 [device-alias CAT]

zone name Z_chili_yahoo vsan 100
* fcid 0x801400 [device-alias chilli]
* fcid 0x803500 [device-alias yahoo]

zone name Z_tom_tommy vsan 100
* fcid 0x801400 [device-alias toma]
  pwwn 0x803460 [device-alias tommya]

我想将其打印如下 - 从区域字开始直到空白行将该行转换为并排打印。

zone name Z_ZEBRA_TIGER vsan 900  * fcid 0x801e00 [device-alias TEST]  * fcid 0x3d8b40 [device-alias TIGER1]  * fcid 0x3d8bc0 [device-alias TIGER2]  * fcid 0x3d8b60 [device-alias CAT]
zone name Z_chili_yahoo vsan 100  * fcid 0x801400 [device-alias chilli]  * fcid 0x803500 [device-alias yahoo]
zone name Z_tom_tommy vsan 100  * fcid 0x801400 [device-alias toma]    pwwn 0x803460 [device-alias tommya]

我尝试使用tr,没有运气。有人可以帮忙吗? 通过sed或awk实现这一目标的任何简单方法。

3 个答案:

答案 0 :(得分:6)

使用awk

$ awk -v RS="" -F'\n' -v OFS=" " '{$1=$1;print}' foo.txt
zone name Z_ZEBRA_TIGER vsan 900 * fcid 0x801e00 [device-alias TEST] * fcid 0x3d8b40 [device-alias TIGER1] * fcid 0x3d8bc0 [device-alias TIGER2] * fcid 0x3d8b60 [device-alias CAT]
zone name Z_chili_yahoo vsan 100 * fcid 0x801400 [device-alias chilli] * fcid 0x803500 [device-alias yahoo]
zone name Z_tom_tommy vsan 100 * fcid 0x801400 [device-alias toma]   pwwn 0x803460 [device-alias tommya]

如何运作

  • -v RS=""

    使用空行作为记录分隔符。

  • -F'\n'

    使用换行作为输入的字段分隔符。

  • -v OFS=" "

    在输出中使用空格作为字段分隔符。

  • $1=$1

    这将第一个字段设置为等于它自己。这会产生信号表明线路已被更改的效果,这将导致awk在输出时用新的字段分隔符替换旧的字段分隔符。

  • print

    打印记录。

简短表格

正如约翰所指出的那样,可以缩短形式。首先,因为输出字段分隔符默认是空格,所以我们不需要显式设置它。其次,可以使用隐式print。因此,上述命令在功能上等同于:

awk -v RS="" -F'\n' '{$1=$1}1' foo.txt

使用sed

$ sed ':a;N;$!ba; s/\n/ /g; s/ zone name/\nzone name/g' foo.txt
zone name Z_ZEBRA_TIGER vsan 900 * fcid 0x801e00 [device-alias TEST] * fcid 0x3d8b40 [device-alias TIGER1] * fcid 0x3d8bc0 [device-alias TIGER2] * fcid 0x3d8b60 [device-alias CAT] 
zone name Z_chili_yahoo vsan 100 * fcid 0x801400 [device-alias chilli] * fcid 0x803500 [device-alias yahoo] 
zone name Z_tom_tommy vsan 100 * fcid 0x801400 [device-alias toma]   pwwn 0x803460 [device-alias tommya] 

这会立即读取整个文件。如果输入文件很大(对于内存来说太大),请使用awk解决方案。

如何运作

  • :a;N;$!ba;

    这会立即读取整个文件。

  • s/\n/ /g;

    这将用空格替换所有换行符。

  • s/ zone name/\nzone name/g

    这会在短语zone name出现之前添加换行符。

答案 1 :(得分:0)

sed -n '/^$/!{H;$!b
             }
        s/.*//;x;s/.//;s/\n/ /g;p' YourFile

  • -n:仅按需打印
  • /^$/!:如果不是白线
    • H:将行附加到缓冲区。
    • $!b如果不是文件的结尾(最后一行),请对脚本进行循环处理(使用下一行重启)
  • s/.*//;x;清空当前行并将其与缓冲区交换
  • s/.//;s/\n/ /g:删除第一个字符(第一个追加的新行)并将所有新行更改为空格
  • p:打印结果并循环到下一行

答案 2 :(得分:0)

Perl:

perl -00 -nE 's/\n/ /g; say' foo.txt
  • -00一次读取文件