Adicione uma palavra específica a cada linha

5

Eu tenho um arquivo como aqui arquivo.txt

bbb-ccc-cccc#
   aasdf  asdas asdasa fgdg
   asdfa  asfdas  adfaq  asfa
   afdaf  fafa  fafd  afafa
bbb-ccc-cccc#

Eu quero pegar a palavra que termina em # e quero adicioná-la a cada linha como a primeira palavra.

sed 's/bbb-ccc-cccc#/^/' < file.txt > newfile.txt

Eu não conheço a palavra antes de # assinar antes, então meu ponto é encontrar a palavra que termina com # e colocá-la no começo de cada linha. Para este arquivo.txt eu preciso como aqui:

bbb-ccc-cccc#
bbb-ccc-cccc#   aasdf  asdas asdasa fgdg
bbb-ccc-cccc#   asdfa  asfdas  adfaq  asfa
bbb-ccc-cccc#   afdaf  fafa  fafd  afafa
bbb-ccc-cccc#
    
por prestruggler 16.02.2017 / 12:49

7 respostas

10

com perl :

perl -lpe 'if (/\H+#/) {$word = $&} else {$_ = $word . $_}'

Ou seja, se encontrarmos uma sequência de caracteres não-brancos ( \H+ ) seguida por um # em uma linha, usaremos isso ( $& é o que corresponde à regexp) como a palavra a ser inserido no início das seguintes linhas.

Mesmo com awk :

awk '
  match($0, /[^[:blank:]]+#/) {
    word = substr($0, RSTART, RLENGTH)
    print
    next
  }
  {print word $0}'

Mesmo com sed (usando o espaço de espera para armazenar a palavra ):

sed '
  /[^[:blank:]]\{1,\}#/ {
    h; # save the line in the hold space
    s//\
&\
/; # put newlines on each side of the matched word
    s/.*\n\(.*\)\n//; # remove every thing but the word
    x; # swap hold and pattern space so that now the hold
       # space contains the word. And branch off:
    b
  }
  # for the other lines:
  G; # append the hold space to the pattern space
  s/\(.*\)\n\(.*\)//; # move the word to the beginning'

Se você deseja corresponder apenas a word# s que estão no final de uma linha, substitua # por #$ nos três comandos acima.

    
por 16.02.2017 / 12:55
7

Usando awk :

$ awk '/^[^ ]*#$/ { prefix = $0; print; next } { print prefix, $0 }' file
bbb-ccc-cccc#
bbb-ccc-cccc#    aasdf  asdas asdasa fgdg
bbb-ccc-cccc#    asdfa  asfdas  adfaq  asfa
bbb-ccc-cccc#    afdaf  fafa  fafd  afafa
bbb-ccc-cccc#

Imprime cada linha com um prefixo. O prefixo é obtido de qualquer linha que corresponda ao padrão ^[^␣]*#$ , ou seja, que consiste inteiramente em caracteres não espaciais e termina com # . Essas linhas são impressas sem um prefixo adicional e o processamento continua com a próxima linha de entrada.

    
por 16.02.2017 / 14:17
3

Aqui minha solução com gnu sed :

sed '/\(.*\)#/{h;:y;n;/\(.*\)#/b;G;s/\(.*\)\n\(.*\)//;by}' test.txt

Explicação rápida:

  • h copia o buffer atual para "manter espaço"
  • G acrescenta "espaço de espera" ao buffer atual (adicionando um carryreturn que precisa ser removido)
  • : xxx são rótulos
  • bxxx são gotos. "b" sozinho vai para o final do script
  • n imprime o buffer atual e lê a próxima linha

Aqui minha solução com o bash:

while IFS='' read -r x;do if [[ "$x" = *# ]] ; then if [ "$p" = "$x" ]; then p=''; else p="$x"; x=''; fi ; fi; printf '%s%s\n' "$p" "$x";done < test.txt
    
por 16.02.2017 / 14:46
2

com gnu sed :

sed -n -e ' /.*#$/ { p; h; b; };' \
       -e '{ H; x; s/[\n[:blank:]]\+/ /; p; s/\(.*#\).*//; h; }' \
        file.txt

A idéia geral é armazenar a linha ...# no espaço de espera e anexá-la na linha de início nas linhas subseqüentes não ...# (no espaço padrão).

    
por 16.02.2017 / 13:59
2

No bash:

#!/bin/bash

# grab one of the lines ending in #
prefix=$(egrep '#$' file | head -1)

cat file | while read line
do
    # if the line ends in a #, just print it
    if [[ $line =~ \#$ ]]
    then
        echo $line
    else
        # print the line prefixed with the $prefix
        printf -- "%s %s\n" "$prefix" "$line"
    fi
done

[[ $line =~ \#$ ]] é uma instrução regex if, mesma regex que no egrep . Se o seu shell não gostar, você pode substituí-lo por if egrep -q '#$' <<< line; then .

    
por 16.02.2017 / 23:26
1
sed -e '
   /#$/!{
      G
      s/\(.*\)\n\(.*\)//
      b
   }
   h
' 
    
por 16.02.2017 / 14:46
1

Solução Python:

#!/usr/bin/env python
import sys
prefix = ""
with open(sys.argv[1]) as fd:
    for line in fd:
        new_line = line.rstrip()
        if new_line.endswith('#'):
            prefix = new_line
        else:
            new_line = prefix + new_line
        print(new_line)

Execução de teste:

$ ./append_word.py input.txt                                       
bbb-ccc-cccc#
bbb-ccc-cccc#   aasdf  asdas asdasa fgdg
bbb-ccc-cccc#   asdfa  asfdas  adfaq  asfa
bbb-ccc-cccc#   afdaf  fafa  fafd  afafa
bbb-ccc-cccc#

A maneira como funciona é simples. Nós lemos o arquivo linha por linha, retirando espaços finais ou novos caracteres do final. Registramos o prefixo em cada linha se essa linha terminar com # character. Se a linha não terminar em # , sabemos que essa linha precisa ser modificada. Finalmente, imprimimos a linha, independentemente de ter sido modificada ou não.

    
por 16.02.2017 / 16:11