使用awk或sed对以pattern开头的行进行排序

问题描述 投票:2回答:3

我想打印路由器配置并仅排序以模式crypto isakmp key 6开头的行。

重要的是,我想将这些行保留在同一个地方,因此这些行之前和之后的所有行应该保持在相同的位置和顺序(未排序)。

示例输入文件:

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

然后我想打印以crypto isakmp key 6开头的SORTED行。

最后,我想打印文件的其余部分(也是随机的行数):

ccc ddd eee
fff ggg hhh iii
123 456

我通过许多操作来管理这个,包括获取crypto isakmp key 6的第一个和最后一个位置并使用tail / head命令,但它非常复杂,我想知道AWK / SED中是否有选项可能是其他linux工具来管理指定行。请解释一下您的命令的作用。

预期输出(加密排序休息完整):

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
linux bash sorting awk sed
3个回答
3
投票

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

asort函数所需的GNU awk。

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

Explanation

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(i.e 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 i.e not crypto lines. We could have also used y'

With meaningful names

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

0
投票

您没有告诉我们您想要排序的内容,或者您​​希望如何排序,或者向我们展示预期的输出,所以这是一个猜测,但可能是或者接近您想要的:

$ 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. * for sorted_in。


0
投票

这是我做的:

# 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

我希望没有这么多步骤,这可以简单地完成。

© www.soinside.com 2019 - 2024. All rights reserved.