Aqui está um jeito Perl:
$ perl -lne '/^\*(.*)/ || print "$_$1"' file
strawberry
raspberry
blueberry
boysenberry
blahblah
blahblah
blahblah
strawberry
blueberry
blah
vegetable
pingpongtable
Explicação
O -n
fará o Perl ler cada linha do arquivo de entrada, salvando-o na variável especial $_
, o -l
fará com que ele i) tire novas linhas ( \n
) de cada linha e ii) adicionar uma nova linha a cada chamada de print
. O -e
é o script aplicado a cada linha.
-
/^\*(.*)/
: corresponde linhas que começam com um asterisco e salvam tudo depois do asterisco como $1
(é o que os parênteses fazem).
-
|| print "$_$1"'
: o ||
é um OR
lógico. Portanto, o print
será executado apenas se a linha atual não iniciar com um asterisco. Nesse caso, imprimimos a linha atual ( $_
) junto com o que estiver salvo atualmente como $1
(o padrão após o asterisco).
Como de costume, há muitas maneiras de fazer isso. Um bobo e ineficiente, mas que destaca os recursos de manipulação de strings do shell, é:
$ while read line; do
[[ $line =~ ^\* ]] && pat="${line#\*}" || printf "%s%s\n" "$line" "$pat";
done < file
strawberry
raspberry
blueberry
boysenberry
blahblah
blahblah
blahblah
strawberry
blueberry
blah
vegetable
pingpongtable
Explicação
-
while read line; do ... ; done < file
: este é um loop while
clássico que lerá cada linha do arquivo de entrada file
e salvará como $line
.
-
[[ $line =~ ^\* ]] && pat="${line#\*}"
: se a linha começar com *
, remova tudo depois disso (é isso que o ${line#\*}
faz, para mais detalhes, veja aqui ) e salve-o como $pat
.
* || printf "%s%s\n" "$line" "$pat";
: se o comando anterior falhou (então, a linha não inicia com um asterisco), imprima a linha e o valor atual de $pat
.