3

I've a file like this:

DelegatedAdmin: cn=fb6190f7-4a33-4502-a2d5-dce8dc434570,ou=Named,ou=Identities,ou=Active,ou=Vault<br />
changetype: modify<br />
delete: DelegatedAdmin<br />
dn: cn=311999,ou=Entities,ou=Active,ou=Vault<br />

DelegatedAdmin: cn=fb6190f7-4a33-4502-a2d5-dce8dc434570,ou=Named,ou=Identities,ou=Active,ou=Vault<br />
changetype: modify<br />
delete: DelegatedAdmin<br />
dn: cn=948089,ou=Entities,ou=Active,ou=Vault<br />

DelegatedAdmin: cn=fb6190f7-4a33-4502-a2d5-dce8dc434570,ou=Named,ou=Identities,ou=Active,ou=Vault<br />
changetype: modify<br />
delete: DelegatedAdmin<br />
dn: cn=947458,ou=Entities,ou=Active,ou=Vault<br />

DelegatedAdmin: cn=9776c3f8-f2ee-4b6c-a9a9-32d87b45f7c5,ou=Named,ou=Identities,ou=Active,ou=Vault<br />
changetype: modify<br />
delete: DelegatedAdmin<br />
dn: cn=10717,ou=Entities,ou=Active,ou=Vault<br />

DelegatedAdmin: cn=e0a838f0-3d53-42e8-8dad-bd1d774381de,ou=Named,ou=Identities,ou=Active,ou=Vault<br />
changetype: modify<br />
delete: DelegatedAdmin<br />
dn: cn=1500,ou=Entities,ou=Active,ou=Vault<br />

And it should be changed to this (switching line 1 and line 4)

dn: cn=311999,ou=Entities,ou=Active,ou=Vault<br />
changetype: modify<br />
delete: DelegatedAdmin<br />
DelegatedAdmin: cn=fb6190f7-4a33-4502-a2d5-dce8dc434570,ou=Named,ou=Identities,ou=Active,ou=Vault<br />

dn: cn=948089,ou=Entities,ou=Active,ou=Vault<br />
changetype: modify<br />
delete: DelegatedAdmin<br />
DelegatedAdmin: cn=fb6190f7-4a33-4502-a2d5-dce8dc434570,ou=Named,ou=Identities,ou=Active,ou=Vault<br />

dn: cn=947458,ou=Entities,ou=Active,ou=Vault<br />
changetype: modify<br />
delete: DelegatedAdmin<br />
DelegatedAdmin: cn=fb6190f7-4a33-4502-a2d5-dce8dc434570,ou=Named,ou=Identities,ou=Active,ou=Vault<br />

dn: cn=10717,ou=Entities,ou=Active,ou=Vault<br />
changetype: modify<br />
delete: DelegatedAdmin<br />
DelegatedAdmin: cn=9776c3f8-f2ee-4b6c-a9a9-32d87b45f7c5,ou=Named,ou=Identities,ou=Active,ou=Vault<br />

dn: cn=1500,ou=Entities,ou=Active,ou=Vault<br />
changetype: modify<br />
delete: DelegatedAdmin<br />
DelegatedAdmin: cn=e0a838f0-3d53-42e8-8dad-bd1d774381de,ou=Named,ou=Identities,ou=Active,ou=Vault<br />

How to do this?

2

6 Answers 6

6

Try also

awk '{print $4, $2, $3, $1}' RS= FS="\n" OFS="\n" ORS="\n\n"  file
dn: cn=311999,ou=Entities,ou=Active,ou=Vault<br />
changetype: modify<br />
delete: DelegatedAdmin<br />
DelegatedAdmin: cn=fb6190f7-4a33-4502-a2d5-dce8dc434570,ou=Named,ou=Identities,ou=Active,ou=Vault<br />

using the RS=<empty> for multiline records separated by an empty line, the field separator <NL> to make lines = fields, and then just printing those in the desired order.

2
  • Thx it works :)
    – Dirk
    May 13 at 18:06
  • Can you add, what the command does? May 14 at 13:55
4

Taking a different tack, you could use ed to move the DelegatedAdmin: lines down 3 and the dn: lines up 3:

printf '%s\n' 'g/^DelegatedAdmin:/m+3' 'g/^dn:/m-3' 'w newfile' 'q' | ed -s file

Change 'w newfile' 'q' to plain 'wq' to edit file in place. Testing to standard out:

$ printf '%s\n' 'g/^DelegatedAdmin:/m+3' 'g/^dn:/m-3' ',p' 'Q' | ed -s file
dn: cn=311999,ou=Entities,ou=Active,ou=Vault<br />
changetype: modify<br />
delete: DelegatedAdmin<br />
DelegatedAdmin: cn=fb6190f7-4a33-4502-a2d5-dce8dc434570,ou=Named,ou=Identities,ou=Active,ou=Vault<br />

dn: cn=948089,ou=Entities,ou=Active,ou=Vault<br />
changetype: modify<br />
delete: DelegatedAdmin<br />
DelegatedAdmin: cn=fb6190f7-4a33-4502-a2d5-dce8dc434570,ou=Named,ou=Identities,ou=Active,ou=Vault<br />

dn: cn=947458,ou=Entities,ou=Active,ou=Vault<br />
changetype: modify<br />
delete: DelegatedAdmin<br />
DelegatedAdmin: cn=fb6190f7-4a33-4502-a2d5-dce8dc434570,ou=Named,ou=Identities,ou=Active,ou=Vault<br />

dn: cn=10717,ou=Entities,ou=Active,ou=Vault<br />
changetype: modify<br />
delete: DelegatedAdmin<br />
DelegatedAdmin: cn=9776c3f8-f2ee-4b6c-a9a9-32d87b45f7c5,ou=Named,ou=Identities,ou=Active,ou=Vault<br />

dn: cn=1500,ou=Entities,ou=Active,ou=Vault<br />
changetype: modify<br />
delete: DelegatedAdmin<br />
DelegatedAdmin: cn=e0a838f0-3d53-42e8-8dad-bd1d774381de,ou=Named,ou=Identities,ou=Active,ou=Vault<br />
3
  • 1
    Very nice ed solution. =) May 13 at 21:39
  • 2
    @ForeverCuber thanks - tbh I'd probably end up using awk irl, but it's fun to play with the less popular tools sometimes May 13 at 21:58
  • When awk is too popular for your tastes... :)
    – chicks
    May 17 at 19:35
3

You might find a better answer in the existing thread:
Change the order of lines in a file

There are some really good answers there, it seems. This may not help if you need this done "in place"; but I extrapolated the following solution from there using Perl:

https://unix.stackexchange.com/a/368429/344329

The script process the whole file, for each line (stored in $_) it will get the next two lines ($l2 and $l3) and print them in the requested order: line1, line3, line2.

The solution there is:

perl -ne '$l2=<>; $l3=<>; print $_,$l3,$l2;' input.txt

For your use case you might try something like this:

perl -ne '$l2=<>; $l3=<>; $l4=<>; $l5=<>; print $l4,$l2,$l3,$_,$l5; if(eof) { exit; } ' input.txt >> output.txt

To be transparent: I am no expert, so I am not confident this is the best way for you.

1
  • 1
    Thx it works :)
    – Dirk
    May 13 at 18:08
2

Using Raku (formerly known as Perl_6)

[Adds extra blank line at end]:

raku -ne 'my ($L1,$L2,$L3,$L4) = (get) xx 4; .put for $L3, $L1, $L2, $_, ($L4 // "");'   

#OR

raku -e 'my @a.=push($_) if .chars for lines; put($_ ~ "\n") for @a.rotor(4)>>.[3,1,2,0]>>.join("\n");' 

[Doesn't add extra blank line at end]:

raku -ne 'my ($L1,$L2,$L3,$L4) = (get) xx 4; .put for $L3, $L1, $L2, $_; $L4.defined ?? $L4.put !! next;' 

#OR

raku -e 'my @a.=push($_) if .chars for lines; .put for @a.rotor(4)>>.[3,1,2,0]>>.join("\n").join("\n\n");' 

First and third examples are similar to Perl5 code posted by @ForeverCuber, and bears a vague resemblance to awk code posted by @RudiC. First/third examples use -ne commandline flags. Second/fourth examples push lines onto an @-sigiled array.

For the first example the -ne commandline flags means the first line loads into $_, Raku's topic variable. Raku is instructed to get 4 successive lines, which load into each of ($L1,$L2,$L3,$L4). The Record Separator is represented by $L4 which, when undefined (at end), is handled using Raku's // defined-OR operator. Thus "" blank string is output if left-side of // evaluates to undefined. Printing is simplified without any joins and by the use of put only.

Second example pushes lines onto an array, @a. Blank lines are skipped via the conditional if .chars. Array elements are rotored together (grouped into 4-element sublists/records), reordered with [3,1,2,0] indexing, and joined with one call to join("\n"). Printing of records is simplified by use of put($_ ~ "\n"), which demonstrates that string concatenation is accomplished via ~ tilde in Raku.

Third example is similar to first example in that it uses -ne commandline flags, and again, no joins are used. However undefined last line is handled better by Raku's "Test ?? True !! False" ternary operator (i.e. $L4.defined ?? $L4.put !! next;). Thus no extra blank line is added at the end. Note: print "" could be used here, in place of next.

Fourth example is similar to second example, except output is built up by two successive calls to join, which recreates the original record spacing (and no extra blank line is added at the end). The first >>.join("\n") call maps into the rotored record to join the 4 lines into a single array element. The second .join("\n\n") takes the resultant 5 array elements (records) and joins them with a blank space in-between each, recreating the input but with the desired line-ordering.


Sample Input (lines have been numbered):

1 DelegatedAdmin: cn=fb6190f7-4a33-4502-a2d5-dce8dc434570,ou=Named,ou=Identities,ou=Active,ou=Vault<br />
2 changetype: modify<br />
3 delete: DelegatedAdmin<br />
4 dn: cn=311999,ou=Entities,ou=Active,ou=Vault<br />

5 DelegatedAdmin: cn=fb6190f7-4a33-4502-a2d5-dce8dc434570,ou=Named,ou=Identities,ou=Active,ou=Vault<br />
6 changetype: modify<br />
7 delete: DelegatedAdmin<br />
8 dn: cn=948089,ou=Entities,ou=Active,ou=Vault<br />

9 DelegatedAdmin: cn=fb6190f7-4a33-4502-a2d5-dce8dc434570,ou=Named,ou=Identities,ou=Active,ou=Vault<br />
10 changetype: modify<br />
11 delete: DelegatedAdmin<br />
12 dn: cn=947458,ou=Entities,ou=Active,ou=Vault<br />

13 DelegatedAdmin: cn=9776c3f8-f2ee-4b6c-a9a9-32d87b45f7c5,ou=Named,ou=Identities,ou=Active,ou=Vault<br />
14 changetype: modify<br />
15 delete: DelegatedAdmin<br />
16 dn: cn=10717,ou=Entities,ou=Active,ou=Vault<br />

17 DelegatedAdmin: cn=e0a838f0-3d53-42e8-8dad-bd1d774381de,ou=Named,ou=Identities,ou=Active,ou=Vault<br />
18 changetype: modify<br />
19 delete: DelegatedAdmin<br />
20 dn: cn=1500,ou=Entities,ou=Active,ou=Vault<br />

Sample Output:

4 dn: cn=311999,ou=Entities,ou=Active,ou=Vault<br />
2 changetype: modify<br />
3 delete: DelegatedAdmin<br />
1 DelegatedAdmin: cn=fb6190f7-4a33-4502-a2d5-dce8dc434570,ou=Named,ou=Identities,ou=Active,ou=Vault<br />

8 dn: cn=948089,ou=Entities,ou=Active,ou=Vault<br />
6 changetype: modify<br />
7 delete: DelegatedAdmin<br />
5 DelegatedAdmin: cn=fb6190f7-4a33-4502-a2d5-dce8dc434570,ou=Named,ou=Identities,ou=Active,ou=Vault<br />

12 dn: cn=947458,ou=Entities,ou=Active,ou=Vault<br />
10 changetype: modify<br />
11 delete: DelegatedAdmin<br />
9 DelegatedAdmin: cn=fb6190f7-4a33-4502-a2d5-dce8dc434570,ou=Named,ou=Identities,ou=Active,ou=Vault<br />

16 dn: cn=10717,ou=Entities,ou=Active,ou=Vault<br />
14 changetype: modify<br />
15 delete: DelegatedAdmin<br />
13 DelegatedAdmin: cn=9776c3f8-f2ee-4b6c-a9a9-32d87b45f7c5,ou=Named,ou=Identities,ou=Active,ou=Vault<br />

20 dn: cn=1500,ou=Entities,ou=Active,ou=Vault<br />
18 changetype: modify<br />
19 delete: DelegatedAdmin<br />
17 DelegatedAdmin: cn=e0a838f0-3d53-42e8-8dad-bd1d774381de,ou=Named,ou=Identities,ou=Active,ou=Vault<br />

https://raku.org

1

With sed:

sed '/^Delegate/{N;N;N;s/\(.*\)\(\n.*\n.*\n\)\(.*\)/\3\2\1/;}'

Or, making use of the hold space:

sed -ne '/^Delegate/{h;n;N;G;x;n;G;}' -e p
0

perl one liner

perl -lne '
  print reverse $_, /./ ? (<>.<>, $,.<>) : ();
' file
  • -n reads files line by line and the line is held inside the $_ variable.
  • the builtin reverse in a list context, as is provided in the print statement, the arguments are reversed.
  • the next lineis accessed by the diamond operator <> and it includes the newline.
  • so we have the order of reverse arguments list as:
    • 1 2 3 4
    • $_ (<>.<>), ("".<>)
    • outputs: _ 4 2 3 1
    • ("".<>), (<>.<>), $_
  • please be aware that reverse cannot peek inside of brackets, so the order inside the brackets is retained.
1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.