Reverte uma linha no sed?

6
 echo 1234 |   sed '
       /\n/ !G
       s/\(.\)\(.*\n\)/&/
       //D
       s/.//
     ' 

Não consigo compreender o código sed acima.

meu entendimento é:

PATTERN SPACE=1234
first operation /\n/ !G ---> 1234\n(if \n is  not found it is appended at th end)
                s/\(.\)\(.*\n\)/&/ ----> 1234\n234\n1
                //D ----> \n234\n1(deletes upto newline and commands
                                   from the beginning are applied to the 
                                   existing pattern space)
PATTERN SPACE=\n234\n1
second operation /\n/ !G ---> skipped since  \n234\n1 has newline now
                 s/\(.\)\(.*\n\)/&/ ----> \n234\n1234\n
                 //D ----> \n234\n1234\n

Parece que estou fazendo algo errado.

    
por munish 31.10.2013 / 07:28

1 resposta

9

Existe um loop neste código que é confuso para ver. Este pouco:

   s/\(.\)\(.*\n\)/&/
   //D

Mantém o loop, mudando os caracteres 234\n1 para 34\n21 até ficarmos com \n4321 , e então ele sai do loop.

A descrição por catonmat está correta, então estou incluindo aqui: 37 . Inverta uma linha (emula o comando "rev" do Unix). .

trecho

The first line "/\n/ !G" appends a newline to the end of the pattern space if there was none.

The second line "s/\(.\)\(.*\n\)/&/" is a simple s/// expression which groups the first character as and all the others as . Then it replaces the whole matched string with "&", where "&" is the whole matched text (""). For example, if the input string is "1234" then after the s/// expression, it becomes "1234\n234\n1".

The third line is "//D". This statement is the key in this one-liner. An empty pattern // matches the last existing regex, so it's exactly the same as: /\(.\)\(.*\n\)/D. The "D" command deletes from the start of the input till the first newline and then resumes editing with first command in script. It creates a loop. As long as /\(.\)\(.*\n\)/ is satisfied, sed will resume all previous operations. After several loops, the text in the pattern space becomes "\n4321". Then /\(.\)\(.*\n\)/ fails and sed goes to the next command.

The fourth line "s/.//" removes the first character in the pattern space which is the newline char. The contents in pattern space becomes "4321" -- reverse of "1234".

There you have it, a line has been reversed.

    
por 31.10.2013 / 09:20

Tags