Bourne shell:根据多个标准拆分字符串(iptables多端口限制)

时间:2015-03-09 12:56:28

标签: string shell split sh

我正在Bourne shell中编写一个例程来命令iptables,它会大量使用“multiport”参数。

iptables允许最多15个对多端口参数的引用。这些引用可以是单独的(计数1)或范围(计数2)。

对于iptables multiport,我需要以可用的方式打破在单个和范围之间混合的一长串端口。

e.g。给出18个参考列表18个单独的端口和2个范围:

21,22,23,24,25,26,27,28,29,30:40,60,61,62,63,64,65:70

我正在尝试找出一种方法将字符串和任何类似的字符串分成最多15个引用的集合,例如15 + 3:

21,22,23,24,25,26,27,28,29,30:40,60,61,62,63
64,65:70

诀窍是:范围不能在不同的行上分割。因此,如果原始输入是:

21,22,23,24,25,26,27,28,29,30:40,60,61,62,63:64,65:70

我需要拆分(14 + 4):

21,22,23,24,25,26,27,28,29,30:40,60,61,62
63:64,65:70

有没有聪明的方法来实现这一点,也许使用awk?

1 个答案:

答案 0 :(得分:0)

这是一个简单的Awk脚本,可以在同一行上收集尽可能多的同类项目。

awk -v RS=',' -F : '{ gsub(/\n$/, "") }
    NF > 1 { r=(r ? r "," : "") $0;                                                                              
        if (r ~ /([^,]*,){6}/) { print r; r=""; } next }                        
    { s=(s ? s "," : "") $0;                                                    
        if (s ~ /([^,]*,){14}/) { print s; s=""; } }                            
    END { if (r && s) {                                                         
            p = r "," s; if (p !~ /([^,:]*[:,]){15}/) { print p; r=s="" } }     
        if (r) print r ; if (s) print s }'

更改后的RS(记录分隔符)表示逗号被拆分,就像它们是换行符一样,并且在这些记录中("行"),冒号被视为字段分隔符。然后我们只检查输入中是否有两个以上的字段,并在打印批次之前收集最多8对或15个单例。

使用输入

21:22,23,24,25,26,27,28,29,30:40,60,61,62,63,64,65:70

打印

21:22,30:40,65:70
23,24,25,26,27,28,29,60,61,62,63,64

您可以在此处播放:http://ideone.com/a3PCzs