BASH对从模式开始的行进行sorting

我想要打印路由器configuration,只sorting以“crypto isakmp key 6”开头的行。 重要的是,我想在同一个地方留下那些行,所以在这行之前和之后应该保持在同一个地方(不sorting)。

示例cfg文件:

123 345 678 901 bla bla bla ble ble ble crypto isakmp key 6 kokofeofepokpfowkfpwjeiofjwiojefiow address 123.456.789.012 crypto isakmp key 6 ofjwiojefiow352okdwofkwkfi9i42kpfsej09f09j4 address 123.456.789.012 crypto isakmp key 6 9i42kpfsej09f09j4ofjwiojefiow352okdwofkwkfi address 123.456.789.012 crypto isakmp key 6 9j4ofjwiojefiow352okdwofkwkfi9i42kpfsej09f0 address 123.456.789.012 ccc ddd eee fff ggg hhh iii 123 456 

所以首先我想打印不变(随机数行):

 123 345 678 901 bla bla bla ble ble ble 

然后我想打印SORTED行开始encryptionisakmp键6。

最后,我想打印其余的文件不变(也随机计数的行):

 ccc ddd eee fff ggg hhh iii 123 456 

我已经通过许多操作来pipe理这个操作,包括获得“crypto isakmp key 6”的第一个和最后一个位置以及使用tail / head命令,但是它非常复杂,我不知道AWK / SED中是否有其他的Linux工具可以pipe理它指定的行。 请解释一下你的命令是怎么做的。

预期的输出(密码sorting完整):

 123 345 678 901 bla bla bla ble ble ble crypto isakmp key 6 9i42kpfsej09f09j4ofjwiojefiow352okdwofkwkfi address 123.456.789.012 crypto isakmp key 6 9j4ofjwiojefiow352okdwofkwkfi9i42kpfsej09f0 address 123.456.789.012 crypto isakmp key 6 kokofeofepokpfowkfpwjeiofjwiojefiow address 123.456.789.012 crypto isakmp key 6 ofjwiojefiow352okdwofkwkfi9i42kpfsej09f09j4 address 123.456.789.012 ccc ddd eee fff ggg hhh iii 123 456 

问候,迈克

不要完全理解你的意思是按排序,但这将按字母顺序对加密行进行排序,并保留其他字符

必需的GNU awk为asort函数。

 awk 'y=/crypto isakmp key 6/{x=1;a[NR]=$0} x&&!y{x=asort(a);for(i=1;i<=x;i++)print a[i];x=0};!x' file 123 345 678 901 bla bla bla ble ble ble crypto isakmp key 6 9i42kpfsej09f09j4ofjwiojefiow352okdwofkwkfi address 123.456.789.012 crypto isakmp key 6 9j4ofjwiojefiow352okdwofkwkfi9i42kpfsej09f0 address 123.456.789.012 crypto isakmp key 6 kokofeofepokpfowkfpwjeiofjwiojefiow address 123.456.789.012 crypto isakmp key 6 ofjwiojefiow352okdwofkwkfi9i42kpfsej09f09j4 address 123.456.789.012 ccc ddd eee fff ggg hhh iii 123 456 

说明

 y=/crypto isakmp key 6/ #variable y is set to 1 if the line contains this regex, 0 if not { #The following code block within the brackets is executed if y is non zero x=1 #Set x to 1(ie true),done every match because it is less hassle and has no negative #side effects a[NR]=$0 #Create array element in array a with a key of NR(line number,doesn't actually matter what #it is though just has to be unique each line) and a value of $0(the line) } #End that block x&&!y #If x(set in the previous block to 1) is set and y isn't (meaning we have encountered a #crypto line but the one we are currently on isn't a crypto line) then { #Open block like before x=asort(a) #Sort the array a, and set x to the number of elements for(i=1;i<=x;i++) #for each element print a[i] #Print the element , note the loop ends here as we have not enclosed in brackets x=0 #Set x to 0(false) } #End block !x #Default action for awk is to print the line if an command returns true, so will print any #line where x is not set or is 0 ie not crypto lines. We could have also used y' 

有意义的名字

 awk 'InBlock=/crypto isakmp key 6/{Stored=1;Lines[NR]=$0} Stored&&!InBlock{ Count=asort(Lines) for(i=1;i<=Count;i++)print Lines[i] Stored=0 } !InBlock' file 

你不要告诉我们你想要排序什么,或者你想如何排序,或者向我们展示预期的输出,所以这是一个猜测,但也许它是或接近你想要的:

 $ cat tst.awk /crypto isakmp key 6/ { buf[$0] gotBuf = 1 next } gotBuf { PROCINFO["sorted_in"] = "@ind_str_asc" for (line in buf) { print line } gotBuf = 0 } { print } $ awk -f tst.awk file 123 345 678 901 bla bla bla ble ble ble crypto isakmp key 6 9i42kpfsej09f09j4ofjwiojefiow352okdwofkwkfi address 123.456.789.012 crypto isakmp key 6 9j4ofjwiojefiow352okdwofkwkfi9i42kpfsej09f0 address 123.456.789.012 crypto isakmp key 6 kokofeofepokpfowkfpwjeiofjwiojefiow address 123.456.789.012 crypto isakmp key 6 ofjwiojefiow352okdwofkwkfi9i42kpfsej09f09j4 address 123.456.789.012 ccc ddd eee fff ggg hhh iii 123 456 

上面使用的GNU awk 4. *用于sorted_in。

这是我做的:

 # get interesting lines with numbers LINER1=`grep -n "^crypto isakmp key 6" r1` # get interesting lines without numbers for later output LINER1F=`grep "^crypto isakmp key 6" r1` # get whole config rows count LENGTHR1=`wc -l r1|awk '{print $1}'` # get 1st interesting line number STARTR1=`echo "$LINER1" | head -1 | cut -f 1 -d:` # get last interesting line number ENDR1=`echo "$LINER1" | tail -1 | cut -f 1 -d:` # assign 1st segment to variable SEGMENT1R1=`head -n $(( $STARTR1 - 1 )) r1` # assign interesting sorted segment to next variable SEGMENT2R1=`echo "$LINER1F"|sort` # assign last segment to variable SEGMENT3R1=`tail -n $(( $LENGTHR1 - $ENDR1 )) r1` # output whole config with sorted segment to file echo "$SEGMENT1R1" > r1 echo "$SEGMENT2R1" >> r1 echo "$SEGMENT3R1" >> r1 

我希望这可以做简单的方法没有太多的步骤。