extrair string antes dos números e depois do sublinhado

extrair string antes dos números e depois do sublinhado

A string original é assim:

str-str001-002_01
str-str005-006_05

Gostaria de extrair a string antes do número e depois do sublinhado, então ficaria assim:

str-str_01
str-str_05

Lembro que o sed poderia separar o padrão em grupos como este:

 sed -n 's/\(^.*\)\([0-9]-[0-9]\)\(.*$\)/\1\3/p'

mas imprime:

str-str0002_01

Então me lembro que [0-9] é apenas um número, então tentei com o sinal + ou *. Então dá um resultado vazio.

obs: usando

echo 'str-str001-002_01' | sed -n 's/\(^.*\)\([0-9]-[0-9]\)\(.*$\)/\2/p'

Posso ver que combina 1-0.

Então eu tentei com:

echo 'str-str001-002_01' | sed -n 's/\(^.*\)\([0-9]\+-[0-9]\+\)\(.*$\)/\2/p'

deixou os 2 primeiros números e só corresponde

1-002

então como fazer com que combine001-002

Responder1

Isso fornece a saída necessária:

sed -nE 's/^([^0-9]*).*_([^_]+)$/\1_\2/p'

Saída do seu exemplo

str-str_01
str-str_05

Explicação

  • sed -nE 's/…/…/p'- Use EREs, não imprima linhas a menos que correspondam
  • ^- âncora no início da linha
  • ([^0-9]*)- corresponder a um padrão tão longo quanto possível, que seja pelo menos um caractere que não seja um dígito
  • .*_- combine o máximo possível (incluindo nada), seguido por " _"
  • ([^_]+)- combine o maior padrão possível (pelo menos um caractere) que não seja um sublinhado
  • $- âncora no final da linha
  • \1_\2- substitua a linha inteira pela primeira (…)correspondência, " _", e pela segunda (…)correspondência

A razão pela qual suas tentativas não funcionaram como esperado é porque *(e +) é ganancioso - consumirá tantos caracteres quanto possível que correspondam ao átomo anterior. Então para um ERE (.*)([0-9]+)aplicado a algo como abc123, o .* consumirá abc12, deixando [0-9]+para corresponder apenas 3. Você precisaria de um "não dígito" para restringir a primeira correspondência: ([^0-9]*)([0-9]+)para obter abce 123.

Responder2

$ cat file
str-str001-002_01
str-str005-006_05
$ sed 's/[0-9]\{3\}-[0-9]\{3\}//' file
str-str_01
str-str_05

O comando de substituição aqui é combinar e remover NNN-NNNonde NNNestá uma série de três dígitos.

Para combinarpelo menos umdígito, use 1,no lugar de 3:

$ sed 's/[0-9]\{1,\}-[0-9]\{1,\}//' file
str-str_01
str-str_05

Isso corresponde ao uso +em uma expressão regular estendida. As expressões regulares usadas por sedpadrão são expressões regulares "básicas" e +corresponderiam a um caractere de adição literal. A maioria seddas implementações também oferece suporte a expressões estendidas com -E:

$ sed -E 's/[0-9]+-[0-9]+//' file
str-str_01
str-str_05

Usar *, como em [0-9]*-[0-9]*, não funcionaria, pois corresponderia ao traço str-str(que tem zero dígitos ao seu redor).


Se você sentir que realmente precisa combinar toda a linha e capturar os bits que deseja manter, você também pode fazer isso. O comando a seguir captura os não dígitos iniciais e o bit final, incluindo o sublinhado:

$ sed 's/\([^0-9]*\).*\(_.*\)/\1\2/' file
str-str_01
str-str_05

Isso, no entanto, é IMHO um pouco difícil de decifrar e faz suposições sobre o início e o fim da string que você nunca mencionou na pergunta. O início não pode, por exemplo, conter dígitos antes dos dígitos que você deseja remover, e o final da string será cortado nodurarsublinhado, não necessariamente após os dígitos que você deseja remover se houver vários sublinhados nessa parte da string.

Você sempre pode adicionar mais informações a essa expressão para garantir que apenas o NNN-NNNbit não seja capturado, mas isso tornaria ainda mais difícil entender a expressão.

informação relacionada