这是我的示例文件:
Host dns1
HostName 172.20.4.75
User root
Port 22
我想只打印一个块意味着例如
Host: dns2 HostName: 172.20.4.80 User: root Port: 22
输出:
Distinct
但是在这个示例中,所有块都有4行,可能会达到5行或更多行,所以我想从Host打印到第一个空行或从Host移到第一个空行
我对正则表达式非常不好,需要这个才能完成我的脚本
谢谢
答案 0 :(得分:3)
我认为你基本上想要这个:
gulp taskname --option 123
取消设置记录分隔符,以便将每个块视为记录,然后打印与该模式匹配的记录。
或者使用shell变量:
awk -v RS='' '/dns1/' file
在这两个示例中,我使用的是默认操作为host=dns1
awk -v host="$host" -v RS='' '$0 ~ host' file
的事实。由于您可能会使用{ print }
更改输出,因此您可能需要考虑添加{ printf ... }
语句以避免不必要地处理文件的其余部分。
答案 1 :(得分:2)
类似的awk
$ awk -v RS= -v OFS=' ' '{for(i=1;i<NF;i+=2) $i=$i":"}1' hosts
Host: dns2 HostName: 172.20.4.80 User: root Port: 22
Host: dns1 HostName: 172.20.4.75 User: root Port: 22
Host: dns3 HostName: 172.20.4.76 User: root Port: 22
Host: dns4 HostName: 172.20.4.77 User: root Port: 22
Host: dns5 HostName: 172.20.4.78 User: root Port: 22
Host: dns6 HostName: 172.20.4.79 User: root Port: 22
将以所需的输出格式为您提供所有记录。您可以进一步过滤此输出或添加模式,例如
$ awk -v RS= -v OFS=' ' '{for(i=1;i<NF;i+=2) $i=$i":"} /dns2/' hosts
Host: dns2 HostName: 172.20.4.80 User: root Port: 22
如果要在处理选定记录后退出,则需要稍微更改脚本
$ awk -v RS= -v OFS=' ' '/dns2/{for(i=1;i<NF;i+=2) $i=$i":"; print; exit}' hosts
Host: dns2 HostName: 172.20.4.80 User: root Port: 22
如果要选择除一条记录以外的所有内容,可以否定该模式(并删除退出)
$ awk -v RS= -v OFS=' ' '!/dns2/{for(i=1;i<NF;i+=2) $i=$i":"; print}' hosts
Host: dns1 HostName: 172.20.4.75 User: root Port: 22
Host: dns3 HostName: 172.20.4.76 User: root Port: 22
Host: dns4 HostName: 172.20.4.77 User: root Port: 22
Host: dns5 HostName: 172.20.4.78 User: root Port: 22
Host: dns6 HostName: 172.20.4.79 User: root Port: 22
请注意,sed inplace replacement需要一个中间文件。如果要使用格式化的一个记录替换原始文件,可以在最后一个awk语句中使用此命令模式
$ awk ... > temp && mv temp original
更新:
设置OFS
将更改字段之间的所有分隔符。您希望按name: value
对它们进行逻辑分组,因此请更改脚本
$ awk -v RS= '{for(i=1;i<NF;i++) $i=$i (i%2?":":"\t")}1' hosts
Host: dns2 HostName: 172.20.4.80 User: root Port: 22
Host: dns1 HostName: 172.20.4.75 User: root Port: 22
Host: dns3 HostName: 172.20.4.76 User: root Port: 22
Host: dns4 HostName: 172.20.4.77 User: root Port: 22
Host: dns5 HostName: 172.20.4.78 User: root Port: 22
Host: dns6 HostName: 172.20.4.79 User: root Port: 22
在偶数定位字段后设置制表符分隔符。
答案 2 :(得分:1)
与Tom Fenech方法没有什么不同,因为它使用记录分隔符,但它也与字段分隔符一起使用以获得所需的输出:
awk -v RS='' -F'\n[\t ]*' -v OFS=' ' '/dns1/{$1=$1;print}' file
更改输出字段分隔符时,需要使用$1=$1
(或$0=$0
或其他任何字段)来强制awk重新评估记录和考虑新的字段分隔符。
注意:当使用exit
命令找到匹配的块时,您可以退出awk。这避免了处理文件的所有结尾。
您也只能使用第一个字段测试模式/dns1/
。
awk -v RS='' -F'\n[\t ]*' -v OFS=' ' '$1~/dns1/{$1=$1;print;exit}' file
如果在结果中添加分号,由于修改了字段,$1=$1
技巧就变得无用了。你可以写:
awk -v RS='' -F'\n[\t ]*' -v OFS=' ' '$1~/dns1/{for(i=1;i<=NF;i++){sub(" ", ": ", $i)};print;exit}' file
答案 3 :(得分:1)
打印第3条记录:
$ awk -v RS= -F'\n[[:blank:]]+' -v OFS='\t' 'NR==3{$1=$1; gsub(/ +/,": "); print}' file
Host: dns3 HostName: 172.20.4.76 User: root Port: 22
打印包含dns4
的记录:
$ awk -v RS= -F'\n[[:blank:]]+' -v OFS='\t' '/dns4/{$1=$1; gsub(/ +/,": "); print}' file
Host: dns4 HostName: 172.20.4.77 User: root Port: 22
打印除dns3
,dns4
或dns5
以外的所有记录:
$ awk -v RS= -F'\n[[:blank:]]+' -v OFS='\t' '!/dns[345]/{$1=$1; gsub(/ +/,": "); print}' file
Host: dns2 HostName: 172.20.4.80 User: root Port: 22
Host: dns1 HostName: 172.20.4.75 User: root Port: 22
Host: dns6 HostName: 172.20.4.79 User: root Port: 22
答案 4 :(得分:0)
这可能适合你(GNU sed):
sed -n '/Host dns1/{:a;N;/^\s*$/M!ba;s/\n\s*/ /g;s/\s*$//p}' file
这将重点放在必需的字符串上,然后追加以下行直到空白行,最后操作收集到所需输出中的新字符串。