como posso usar sed para substituir as listas que começam com (*) em um arquivo

4

Usando sed , como posso substituir as linhas que começam com uma estrela e substituí-las por números a partir de 1?

Eu preciso substituir o (*) no punho de uma lista por números usando sed por exemplo >

este arquivo contém uma lista

*linux

*computers

*labs

*questions

para > > > >

este arquivo contém uma lista

1 linux
2 computers
3 labs
4 questions

Eu tentei usar

sed -e 's/*//' file.in > file.out | sed -i = file.out
    
por Abdulaziz Hamoud 07.11.2014 / 03:17

6 respostas

8

Você pode usar o awk:

awk '/^\*/ {sub(/\*/, ++i)} 1' <<END
A list
* one
* two
Blah
* three
END
A list
1 one
2 two
Blah
3 three
    
por 07.11.2014 / 04:31
7

Você pode reproduzir alguns truques - as primeiras linhas numéricas com * somente, depois, remover * e spaces se você quiser

nl -bp^[*] file | sed 's/^\s*\|\s*\*//g'
    
por 07.11.2014 / 10:24
3
{   tr -s \n |
    sed =|
    sed '$!N;s/\n./ /'
} <<\INPUT
*linux

*computers

*labs

*questions
INPUT

OUTPUT

1 linux
2 computers
3 labs
4 questions

nl é o mais óbvio, mas sed pode contar linhas. sed não está sozinho a esse respeito:

sh <<HD
$(sed -n 's/^\*\(.*\)/echo "$LINENO "/p' <infile)
HD

... ou ...

sed -n "s/..*/OUT='&'/p" <infile | 
PS1='${LINENO#0} ${OUT#?}${IFS#??}' dash -i

... ambos imprimem o mesmo que antes (mesmo que seja um pouco bobo) . Eu uso dash explicitamente aqui, porque, por padrão, ele não ativa nenhum leitor de terminal readline . Se dash for seu sh , você pode usar apenas sh , mas se bash estiver vinculado a sh , será necessário usar --noediting para o segundo exemplo para evitar a impressão de OUT=... de material para o terminal também.

E, na verdade, para o seu exemplo de exemplo simples, tudo pode ser feito com nl e tr :

tr -d \* <<\INPUT| nl -s ' ' -w1 -nln
*linux

*computers

*labs

*questions
INPUT

OUTPUT

1 linux

2 computers

3 labs

4 questions
    
por 07.11.2014 / 23:04
3

Eu usaria o perl em vez disso. A sintaxe para isso é muito semelhante a sed 's:

perl -pe 's/^\*/$c++/e' file

Ou, para começar a partir de 1:

perl -pe 's/^\*/++$c/e' file

E para editar o arquivo original:

perl -i -pe 's/^\*/++$c/e' file
    
por 07.11.2014 / 19:53
1

Não consigo encontrar uma solução que use apenas sed , mas isso chega perto. Ele usa apenas sed , recursos internos do shell e cmp e mv . Com algum esforço e um shell moderno, você pode reescrever isso para manter o conteúdo do arquivo nas variáveis do shell e não precisar usar cmp ou mv .

#!/bin/sh
if test $# -ne 1
then
    echo usage: $0 file
    exit 1
fi
num=1    # start numbering at 1
infile="$1"
outfile="$1.out"
mv "$infile" "$outfile"    # set up so initial cmp always fails
while ! cmp -s "$infile" "$outfile" # repeat the sed until no more ^* can be found
do
    mv "$outfile" "$infile"
    # replace the first occurrence of ^* with a number and a space
    sed '0,/^\*/s//'$num' /' "$infile" > "$outfile" 
    num=$(expr $num + 1)
done
rm "$outfile"

teste:

$ cat i
first line
*second
*third
fourth
*fifth
$ ./change i
$ cat i
first line
1 second
2 third
fourth
3 fifth
    
por 07.11.2014 / 21:01
-3

sed não pode fazer cálculos, portanto, isso não é possível de maneira útil.

    
por 07.11.2014 / 03:31