Linux 使用sed在另一行下移动特定行

Linux 使用sed在另一行下移动特定行,linux,shell,sed,Linux,Shell,Sed,我需要找到entryUUID并将其替换为newrdn,然后将该行移到另一行下。此文本文件将具有超过500k的变更类型,因此移动到特定行号将不起作用 文本文件中的原始行: dn: uid=test@testing.com,ou=people,dc=example,dc=com changetype: modrdn deleteoldrdn: 1 newsuperior: ou=people,dc=example,dc=com entryUUID: 6277b4d4e3-xxxx-xxxx-xxxx

我需要找到entryUUID并将其替换为newrdn,然后将该行移到另一行下。此文本文件将具有超过500k的变更类型,因此移动到特定行号将不起作用

文本文件中的原始行:

dn: uid=test@testing.com,ou=people,dc=example,dc=com
changetype: modrdn
deleteoldrdn: 1
newsuperior: ou=people,dc=example,dc=com
entryUUID: 6277b4d4e3-xxxx-xxxx-xxxx-xxxxxxxxxx
我想用newrdn替换entryUUID,然后将此行移到以changetype开头的行下面

理想输出:

dn: uid=test@testing.com,ou=people,dc=example,dc=com
changetype: modrdn
newrdn: 6277b4d4e3-xxxx-xxxx-xxxx-xxxxxxxxxx
deleteoldrdn: 1
newsuperior: ou=people,dc=example,dc=com
我正在使用以下命令;但是,它没有按预期工作(添加新的不正确条目而不是移动行)


单向使用
sed

具有多个条目的示例文件:

dn:uid=test@testing.com,ou=people,dc=example,dc=com
更改类型:modrdn
deleteoldrdn:1
newsuperior:ou=people,dc=example,dc=com
入口UUID:6277b4d4e3-xxxx-xxxx-XXXXXXXXX
---
dn:uid=test@testing.com,ou=people,dc=example,dc=com
更改类型:modrdn
deleteoldrdn:1
newsuperior:ou=people,dc=example,dc=org
入口UUID:7277b4d4e3-xxxx-xxxx-XXXXXXXXX
sed-e'/^deleteoldrdn:/{N;h;d}/^entryUUID://{s/^entryUUID:/newrdn://;G}'input.txt
dn:uid=test@testing.com,ou=people,dc=example,dc=com
更改类型:modrdn
新域名:6277b4d4e3-xxxx-xxxx-XXXXX-XXXXXXXXX
deleteoldrdn:1
newsuperior:ou=people,dc=example,dc=com
---
dn:uid=test@testing.com,ou=people,dc=example,dc=com
更改类型:modrdn
新域名:7277b4d4e3-xxxx-xxxx-XXXXX-XXXXXXXXX
deleteoldrdn:1
newsuperior:ou=people,dc=example,dc=org
工作原理:
/^deleteoldrnd:/{N;h;d}

每次读取以
deleteoldrnd:
开头的行时,也要读取下一行并将其添加到当前模式空间(
N
),将当前保留空间替换为模式空间(
h
),删除模式空间并以新行(
d
)重新开始

/^entryUUID:/{s/^entryUUID:/newrdn://;G}

每次读取以
entryUUID:
开头的行时,将前缀更改为
newrdn:
,然后将保留空间附加到模式空间(
G
),(此时的保留空间是原始文件前面的
deleteoldrdn
newsuperior
行)。然后,图案空间会自动打印出来

如果您使用的是GNU sed(可能是因为您标记了这个[linux]),则有一个变体:

sed-e'/^deleteoldrdn://{N;h;z;N;s/\nentryUUID:/newrdn://;G}input.txt

它使用GNU扩展名
z
在读取同一命令序列中的UUID行之前擦除模式空间,而不是将其拆分为两行。

您也可以使用
ed
,而不是使用
sed-i
就地编辑文件,由于它将一个文件作为一个整体来处理,而不是一次处理一个孤立的行,因此它具有移动行的命令,这大大简化了工作。使用与my
sed相同的输入文件回答:

$ ed -s input.txt <<'EOF'
g/^entryUUID:/s/^entryUUID:/newrdn:/\ 
m -3
w
EOF
$ cat input.txt
dn: uid=test@testing.com,ou=people,dc=example,dc=com
changetype: modrdn
newrdn: 6277b4d4e3-xxxx-xxxx-xxxx-xxxxxxxxxx
deleteoldrdn: 1
newsuperior: ou=people,dc=example,dc=com
---
dn: uid=test@testing.com,ou=people,dc=example,dc=com
changetype: modrdn
newrdn: 7277b4d4e3-xxxx-xxxx-xxxx-xxxxxxxxxx
deleteoldrdn: 1
newsuperior: ou=people,dc=example,dc=org
$ed-s input.txt这可能适合您(GNU-sed):

打印任何行直到一个开头
changetype:
,打印此行并将其后面的行收集到保留空间中,直到行开始
entryUUID:
。用
newrdn:
替换该字符串并打印当前行。将保留空间中收集的行减去前导换行符后追加并打印它们。打印所有其他行

另一种解决方案:

sed '/^changetype:/{:a;N;s/^entryUUID:/newrnd:/m;Ta;s/\(\n.*\)\(\n.*\)/\2\1/}' file

哦,档案中有多个这样的案例,还是只有一个?@Shawn档案中有多个这样的案例。
sed -n '/^changetype:/{p;:a;n;/^entryUUID:/bb;H;ba;:b;s//newrdn:/p;z;x;s/.//};p' file
sed '/^changetype:/{:a;N;s/^entryUUID:/newrnd:/m;Ta;s/\(\n.*\)\(\n.*\)/\2\1/}' file