我正在尝试格式化以下实际输出以使每个磁盘位于同一行
0. ct1d0 <INTEL-ADDPF2KX076T9S-2CV1-6.19TB>
/pci@4,0/pci8086,347c@4/e,487c@0/disk@1
/dev/chassis/SYS/DBP/HDD0/NVME/disk
1. c2t1d0 <INTEL-ADDPF2KX076T9S-2CV1-6.19TB>
/pci@4,0/pci8086,347d@5/apci108e,487c@0/disk@1
/dev/chassis/DBP/HDD1/NVME/disk
2. c3t0d0 <ATA-Min_5300_MAAAD-D3MU-223.57GB>
/pci@0,0/pci8e,4872@17/disk@0,0
/dev/chassis/MB/SSDR0/SSD0/disk
3. c4t2d0 <ATA-Min_5300_MTFD-D3MU-223.57GB>
/pci@0,0/pci08e,4872@17/disk@2,0
/dev/chassis/SYS/MB/SSDR0/SSD1/disk
尝试获得如下所示的预期输出,
0. ct1d0 <INTEL-ADDPF2KX076T9S-2CV1-6.19TB>| /pci@4,0/pci8086,347c@4/e,487c@0/disk@1| /dev/chassis/SYS/DBP/HDD0/NVME/disk|
1. c2t1d0 <INTEL-ADDPF2KX076T9S-2CV1-6.19TB>| /pci@4,0/pci8086,347d@5/apci108e,487c@0/disk@1| /dev/chassis/DBP/HDD1/NVME/disk|
2. c3t0d0 <ATA-Min_5300_MAAAD-D3MU-223.57GB>| /pci@0,0/pci108e,4872@17/disk@0,0| /dev/chassis/MB/SSDR0/SSD0/disk|
3. c4t2d0 <ATA-Min_5300_MTFD-D3MU-223.57GB>| /pci@0,0/pci108e,4872@17/disk@2,0| /dev/chassis/SYS/MB/SSDR0/SSD1/disk|
我在下面尝试过,
cat actual_output | tr -s " " | tr "\n" "|"
结果都是单行,
0. ct1d0 <INTEL-ADDPF2KX076T9S-2CV1-6.19TB>| /pci@4,0/pci8086,347c@4/e,487c@0/disk@1| /dev/chassis/SYS/DBP/HDD0/NVME/disk|1. c2t1d0 <INTEL-ADDPF2KX076T9S-2CV1-6.19TB>| /pci@4,0/pci8086,347d@5/apci108e,487c@0/disk@1| /dev/chassis/DBP/HDD1/NVME/disk|2. c3t0d0 <ATA-Micron_5300_MAAAD-D3MU-223.57GB>| /pci@0,0/pci108e,4872@17/disk@0,0| /dev/chassis/MB/SSDR0/SSD0/disk|3. c4t2d0 <ATA-Micron_5300_MTFD-D3MU-223.57GB>| /pci@0,0/pci108e,4872@17/disk@2,0| /dev/chassis/SYS/MB/SSDR0/SSD1/disk|
现在需要用换行符替换 0. until next 1. contents( ), 这样就会得到预期的结果。 我们有任何正则表达式来做同样的事情吗?
TIA
paste
如果每组总是 3 行,则串行模式可以工作:
paste -sd'||\n'
输出:
0. ct1d0 <INTEL-ADDPF2KX076T9S-2CV1-6.19TB>| /pci@4,0/pci8086,347c@4/e,487c@0/disk@1| /dev/chassis/SYS/DBP/HDD0/NVME/disk
1. c2t1d0 <INTEL-ADDPF2KX076T9S-2CV1-6.19TB>| /pci@4,0/pci8086,347d@5/apci108e,487c@0/disk@1| /dev/chassis/DBP/HDD1/NVME/disk
2. c3t0d0 <ATA-Min_5300_MAAAD-D3MU-223.57GB>| /pci@0,0/pci8e,4872@17/disk@0,0| /dev/chassis/MB/SSDR0/SSD0/disk
3. c4t2d0 <ATA-Min_5300_MTFD-D3MU-223.57GB>| /pci@0,0/pci08e,4872@17/disk@2,0| /dev/chassis/SYS/MB/SSDR0/SSD1/disk
使用 GNU
awk
:
$ awk '/^\s/{r=r "| " $0;next} NR!=1{print r "|"} {r=$0} END{print r "|"}' data.txt
0. ct1d0 <INTEL-ADDPF2KX076T9S-2CV1-6.19TB>| /pci@4,0/pci8086,347c@4/e,487c@0/disk@1| /dev/chassis/SYS/DBP/HDD0/NVME/disk|
1. c2t1d0 <INTEL-ADDPF2KX076T9S-2CV1-6.19TB>| /pci@4,0/pci8086,347d@5/apci108e,487c@0/disk@1| /dev/chassis/DBP/HDD1/NVME/disk|
2. c3t0d0 <ATA-Min_5300_MAAAD-D3MU-223.57GB>| /pci@0,0/pci8e,4872@17/disk@0,0| /dev/chassis/MB/SSDR0/SSD0/disk|
3. c4t2d0 <ATA-Min_5300_MTFD-D3MU-223.57GB>| /pci@0,0/pci08e,4872@17/disk@2,0| /dev/chassis/SYS/MB/SSDR0/SSD1/disk|
使用 GNU
sed
:
sed -zE 's/\n\s+/| /g;s/(\n|$)/|&/g' data.txt
0. ct1d0 <INTEL-ADDPF2KX076T9S-2CV1-6.19TB>| /pci@4,0/pci8086,347c@4/e,487c@0/disk@1| /dev/chassis/SYS/DBP/HDD0/NVME/disk|
1. c2t1d0 <INTEL-ADDPF2KX076T9S-2CV1-6.19TB>| /pci@4,0/pci8086,347d@5/apci108e,487c@0/disk@1| /dev/chassis/DBP/HDD1/NVME/disk|
2. c3t0d0 <ATA-Min_5300_MAAAD-D3MU-223.57GB>| /pci@0,0/pci8e,4872@17/disk@0,0| /dev/chassis/MB/SSDR0/SSD0/disk|
3. c4t2d0 <ATA-Min_5300_MTFD-D3MU-223.57GB>| /pci@0,0/pci08e,4872@17/disk@2,0| /dev/chassis/SYS/MB/SSDR0/SSD1/disk|
-z
将整个输入处理为一行,-E
用于扩展正则表达式。 s/\n\s+/| /g
用 |
替换换行符后跟一个或多个空格。 s/(\n|$)/|&/g
在所有剩余的换行符或文件末尾之前插入 |
。
使用 GNU
awk
请尝试以下 awk
代码。仅在所示示例中编写和测试。
awk -v RS='(^|\n)[0-9]+\\.' -v OFS="| " '
rt{
sub(/^\n/,"",RT)
$1=$1
print rt " " $0,_
}
{ rt=RT }
' Input_file
使用任何 awk 并且不依赖于每个输入记录有 3 行:
$ awk '/^[0-9]/{ if (NR>1) print rec; rec=$0; next} {sub(/ */,"| "); rec=rec $0} END{print rec}' file
0. ct1d0 <INTEL-ADDPF2KX076T9S-2CV1-6.19TB>| /pci@4,0/pci8086,347c@4/e,487c@0/disk@1| /dev/chassis/SYS/DBP/HDD0/NVME/disk
1. c2t1d0 <INTEL-ADDPF2KX076T9S-2CV1-6.19TB>| /pci@4,0/pci8086,347d@5/apci108e,487c@0/disk@1| /dev/chassis/DBP/HDD1/NVME/disk
2. c3t0d0 <ATA-Min_5300_MAAAD-D3MU-223.57GB>| /pci@0,0/pci8e,4872@17/disk@0,0| /dev/chassis/MB/SSDR0/SSD0/disk
3. c4t2d0 <ATA-Min_5300_MTFD-D3MU-223.57GB>| /pci@0,0/pci08e,4872@17/disk@2,0| /dev/chassis/SYS/MB/SSDR0/SSD1/disk
如果你真的想要一个
|
添加到每个输出行的末尾,那么只需将每个 print rec
更改为 print rec"|"
.
使用 GNU
sed
$ sed -Ez ':a;s/([0-9]+\.[^\n]*)\n +/\1| /;ta;s/\n|$/|&/g' input_file
0. ct1d0 <INTEL-ADDPF2KX076T9S-2CV1-6.19TB>| /pci@4,0/pci8086,347c@4/e,487c@0/disk@1| /dev/chassis/SYS/DBP/HDD0/NVME/disk|
1. c2t1d0 <INTEL-ADDPF2KX076T9S-2CV1-6.19TB>| /pci@4,0/pci8086,347d@5/apci108e,487c@0/disk@1| /dev/chassis/DBP/HDD1/NVME/disk|
2. c3t0d0 <ATA-Min_5300_MAAAD-D3MU-223.57GB>| /pci@0,0/pci8e,4872@17/disk@0,0| /dev/chassis/MB/SSDR0/SSD0/disk|
3. c4t2d0 <ATA-Min_5300_MTFD-D3MU-223.57GB>| /pci@0,0/pci08e,4872@17/disk@2,0| /dev/chassis/SYS/MB/SSDR0/SSD1/disk|
修改一个数据集只有两行:
$ cat disk.dat
0. ct1d0 <INTEL-ADDPF2KX076T9S-2CV1-6.19TB>
/pci@4,0/pci8086,347c@4/e,487c@0/disk@1
/dev/chassis/SYS/DBP/HDD0/NVME/disk
1. c2t1d0 <INTEL-ADDPF2KX076T9S-2CV1-6.19TB>
/pci@4,0/pci8086,347d@5/apci108e,487c@0/disk@1
/dev/chassis/DBP/HDD1/NVME/disk
2. c3t0d0 <ATA-Min_5300_MAAAD-D3MU-223.57GB>
/pci@0,0/pci8e,4872@17/disk@0,0
3. c4t2d0 <ATA-Min_5300_MTFD-D3MU-223.57GB>
/pci@0,0/pci08e,4872@17/disk@2,0
/dev/chassis/SYS/MB/SSDR0/SSD1/disk
扩展OP的当前代码:
cat disk.dat | tr -s " " | tr "\n" "|" | sed -E "s/\|([0-9])/\|\n\1/g; s/$/\n/"
地点:
sed
脚本的前半部分在管道(\n
)和数字(|
)之间放置一个[0-9]
sed
脚本的第二部分在行尾添加一个\n
另一种
awk
想法:
awk -F'.' ' # input field delimiter is a period
{ sub(/[[:space:]]+/,"",$1) } # remove leading white space from 1st field
($1+0)==$1 { if (NR>1) print ""; pfx="" } # if 1st field is numeric; if beyond 1st row then terminate previous line of output; reset prefix to empty string
{ printf "%s%s|", pfx, $0; pfx=" " } # print prefix plus current line; reset prefix to a single space
END { if (NR>=1) print "" } # if we had at least one row of input then terminate previous line of output
' disk.dat
这两个都会产生:
0. ct1d0 <INTEL-ADDPF2KX076T9S-2CV1-6.19TB>| /pci@4,0/pci8086,347c@4/e,487c@0/disk@1| /dev/chassis/SYS/DBP/HDD0/NVME/disk|
1. c2t1d0 <INTEL-ADDPF2KX076T9S-2CV1-6.19TB>| /pci@4,0/pci8086,347d@5/apci108e,487c@0/disk@1| /dev/chassis/DBP/HDD1/NVME/disk|
2. c3t0d0 <ATA-Min_5300_MAAAD-D3MU-223.57GB>| /pci@0,0/pci8e,4872@17/disk@0,0|
3. c4t2d0 <ATA-Min_5300_MTFD-D3MU-223.57GB>| /pci@0,0/pci08e,4872@17/disk@2,0| /dev/chassis/SYS/MB/SSDR0/SSD1/disk|
您可以将 awk 与模运算符一起使用。在一个条件下:如果当前行不能被 3 整除则管道符号“|”添加,否则添加新行:
awk 'BEGIN{ ORS=""; }{printf "%s%s", $0,(NR%3?"|":"\n");}' actual_output
这可能对你有用(GNU sed):
sed -E '/^\S/{:a;x;1!s/\n(\s)+|$/|\2/gp;d};H;$!d;ba' file
会有两个条件;一行不以空格开头或以空格开头的地方。
如果一行不以空格开头(新记录):
|
并打印结果。如果行以空格开头(中间记录):
注意每次遇到新记录时,都会处理并打印先前存储的记录。还有 first 和 last 之间的对称性以及
x
和 H
的使用的不对称性。
替代方案:
sed -zE 's/\n\s+/| /g;s/.*/&|/gm' file
注意全麦编程的一个很好的例子。第一个替换将所有行减少为单独的记录。第二次替换将
|
附加到每条记录。