Melhorar o comando sed para substituir a primeira instância do caractere e todos os caracteres seguintes?

1

Entrada:

<e1 name="file1" id="id1" anotherId="id2">

Saída desejada:

file1

Eu posso conseguir o que preciso com isso:

echo '<e1 name="file1" id="id1" anotherId="id2">' | sed 's/\(.*name="\)\(.*\)\(".*\)//' | sed 's/".*//'

Saída: file1

Gostaria de melhorar o conjunto de comandos e remover o último canal para sed, se possível. Se eu remover o último canal para sed, não consigo o que quero:

echo '<e1 name="file1" id="id1" anotherId="id2">' | sed 's/\(.*name="\)\(.*\)\(".*\)//'

Saída:

file1" id="id1" anotherId="id2

Como você pode ver, o sed está captando a última aspa e não o primeiro após o arquivo1.

Alguém pode ajudar a melhorar este comando?

    
por phatypus 14.09.2013 / 08:36

2 respostas

2
echo '<e1 name="file1" id="id1" anotherId="id2">' |
  sed -n 's/.*name="\([^"]*\)".*//p'

Ou com o GNU grep se construído com suporte a PCRE:

echo '<e1 name="file1" id="id1" anotherId="id2">' |
  grep -Po 'name="\K[^"]*'
    
por 14.09.2013 / 08:54
2

sed

Você pode simplificá-lo um pouco com esta versão:

$ echo '<e1 name="file1" id="id1" anotherId="id2">' | \
   sed 's/.*name="\(.*\)" id.*//'

Você não precisa envolver tudo com parênteses, apenas as coisas que você está interessado em salvar para uso posterior, para que você possa removê-lo.

grep

Você também pode usar a capacidade de grep de usar o mecanismo de expressões regulares (PCRE) do Perl:

$ echo '<e1 name="file1" id="id1" anotherId="id2">' | \
   grep -Po '(?<=name=")(\w+)(?=")'

A capacidade deste PCRE de olhar para frente e olhar para trás. A notação procura uma sequência de caracteres como "name=" antes do que estamos procurando. Este bit está fazendo isso:

(?<=name=")

Em seguida, ele procura uma série de caracteres de palavras. É o que estamos procurando:

(\w+)

A última parte que está fazendo a antecipação é esta:

(?=")

Está procurando por uma aspa ( " ) após o que estamos procurando.

awk

$ echo '<e1 name="file1" id="id1" anotherId="id2">' | \
   awk '{gsub("\"","");split($2,a,"="); print a[2]}'

Esta variante atribui as aspas duplas ('' '') fazendo uma substituição global:

gsub("\"","")

A string restante seria esta:

<e1 name=file1 id=id1 anotherId=id2>

Assim, podemos deixar awk dividir isso normalmente e a segunda coluna seria o que estamos interessados em obter. Isso seria $2 to awk . Então poderíamos pegar essa variável e então dividir em sinais de igual ( = ).

split($2,a,"=");

Isso dividirá $2 e armazenará os resultados em uma matriz, a . Posteriormente, podemos imprimir o segundo elemento na matriz, sendo tudo do lado direito do sinal de igual de $2 .

file1
    
por 14.09.2013 / 09:00