AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / unix / Perguntas / 758329
Accepted
Rafiq
Rafiq
Asked: 2023-10-07 11:13:05 +0800 CST2023-10-07 11:13:05 +0800 CST 2023-10-07 11:13:05 +0800 CST

Substituindo qualquer string fechada <> por um sinal $ no início da mesma string em um arquivo de texto

  • 772

Tenho alguns arquivos que residem em um sistema Linux, contendo alguns espaços reservados como este arquivo abaixo:

teste.txt:

This is a line with <VARIABLE1>@<VARIABLE2>.
This is a line with <VARIABLE3>.
This is a line with <VARIABLE_UNKNOWN>.
This is another line contains a<b.

Quero alterar este arquivo mostrando como abaixo:

This is a test line with $VARIABLE1@$VARIABLE2.
This is a test line with $VARIABLE3.
This is a test line with $VARIABLE_UNKNOWN.
This is another line contains a<b.

Observe que todas essas variáveis ​​fechadas <>contêm apenas letras maiúsculas, dígitos e sublinhados.

Eu poderia ter usado o seguinte método, mas a<bse tornou a$b.

file_contents=$(<$file_path)
file_contents=${file_contents//</$}
file_contents=$(echo "$file_contents" | tr -d '>')
echo "$file_contents" > test.txt

Estou tentando evitar um sedcomando complexo que se torna muito difícil de depurar. Como posso conseguir isso?

text-processing
  • 4 4 respostas
  • 229 Views

4 respostas

  • Voted
  1. terdon
    2023-10-07T17:33:14+08:002023-10-07T17:33:14+08:00

    Se o problema puder ser declarado como "Desejo converter todas as strings incluídas < >e consistindo em apenas uma ou mais letras maiúsculas, dígitos e sublinhados entre < >si, mas com um $em vez de < >", então você pode fazer o seguinte:

    $ perl -pe 's/<([A-Z\d_]+)>/\$$1/g' file 
    This is a line with $VARIABLE1@$VARIABLE2.
    This is a line with $VARIABLE3.
    This is a line with $VARIABLE_UNKNOWN.
    This is another line contains a<b.
    

    O -pemeio significa "ler o arquivo de entrada linha por linha, aplicar o script fornecido -ee imprimir cada linha". Em seguida, usamos o operador de substituição ( s/OLD/NEW/) com o gsinalizador para substituir todas as ocorrências na linha. Por fim, a regex procura <seguida por uma ou mais (o +que significa uma ou mais) letras ASCII maiúsculas ( A-Z), dígitos decimais ASCII¹ ( \d) ou sublinhados ( _) terminando com >. Agora, como o padrão está entre parênteses ( ([A-Z\d_]+)), nós o "capturamos" e podemos nos referir a ele como $1na substituição. Portanto, substituímos o que correspondemos por a $(que precisa ser escapado como \$) e, em seguida, o que correspondeu: \$$1.


    ¹ pelo menos enquanto a $PERL_UNICODEvariável de ambiente não estiver definida, caso em que poderá corresponder a outros tipos de dígitos decimais. Use o asinalizador para o s///operador para garantir que apenas 0123456789 sejam correspondidos ou substitua \dpor 0-9ou0123456789

    • 2
  2. Best Answer
    Ed Morton
    2023-10-07T20:39:18+08:002023-10-07T20:39:18+08:00

    Como se trata de substituições simples em linhas individuais, o comando sed para fazer isso não seria complexo:

    $ sed -E 's/<([[:upper:][:digit:]_]+)>/$\1/g' file
    This is a line with $VARIABLE1@$VARIABLE2.
    This is a line with $VARIABLE3.
    This is a line with $VARIABLE_UNKNOWN.
    This is another line contains a<b.
    

    ou se o seu sed não tiver -Enenhum sed POSIX:

    sed 's/<\([[:upper:][:digit:]_]\{1,\}\)>/$\1/g' file
    

    Se o seu sed nem for compatível com POSIX, compre um novo , mas para isso em particular você provavelmente poderia fazer:

    sed 's/<\([A-Z0-9_][A-Z0-9_]*\)>/$\1/g' file
    

    Como @chrisdavies aponta , esse provavelmente não é o resultado que você realmente deveria tentar obter, pois ele se transformará <VAR1>27e $VAR127você realmente deveria buscar qualquer um destes:

    $ sed -E 's/<([[:alnum:]_]+)>/${\1}/g' file
    This is a line with ${VARIABLE1}@${VARIABLE2}.
    This is a line with ${VARIABLE3}.
    This is a line with ${VARIABLE_UNKNOWN}.
    This is another line contains a<b.
    

    $ sed -E 's/<([[:alnum:]_]+)>/"${\1}"/g' file
    This is a line with "${VARIABLE1}"@"${VARIABLE2}".
    This is a line with "${VARIABLE3}".
    This is a line with "${VARIABLE_UNKNOWN}".
    This is another line contains a<b.
    

    dependendo do que você está planejando fazer com essa saída.

    FWIW normalmente, quando as pessoas têm strings de espaço reservado no texto, elas não as substituem pelos nomes das variáveis ​​​​do shell, elas as substituem pelo conteúdo das variáveis ​​​​do shell, porque, caso contrário, qual seria o sentido de usar espaços reservados no texto quando você poderia ter acabado de criá-lo com os nomes das variáveis ​​​​do shell em primeiro lugar?

    • 2
  3. jubilatious1
    2023-10-10T06:08:29+08:002023-10-10T06:08:29+08:00

    Usando Raku (anteriormente conhecido como Perl_6)

    ~$ raku -pe 's:g/ \< ( <[A..Z0..9_]>+ ) \> /\$$0/;'  file
    

    Mais uma vez, esta é praticamente uma tradução direta da excelente resposta Perl de @terdon.

    Em Raku,

    1. Modificadores Regex, como global, vão no início do matcher precedido por dois pontos, para fornecer a s:g///forma "global substituto".
    2. Dentro do domínio de reconhecimento, uma classe de caracteres personalizada é criada com <[ ... ]>colchetes delimitados por colchetes angulares. Somente colchetes são usados ​​para agrupar átomos e/ou propriedades de regex (veja o exemplo na parte inferior).
    3. Um intervalo de caracteres é especificado com ..pontos duplos como (por exemplo) A..Zou 0..9.
    4. Raku simplificou as regras de escape de modo que todos os caracteres não alfanuméricos sem sublinhado devem ser citados ou (barra invertida) escapados para serem entendidos como literais dentro de regexes, daí a necessidade de usar e no domínio de \<reconhecimento \>.
    5. As capturas numeradas são especificadas em Raku por parênteses (o mesmo que em Perl), no entanto, essas capturas numeradas começam $0e devem ser usadas no domínio de substituição como tal.
    6. O OP refere-se a substituições errôneas e, muitas vezes, a exigência de barra invertida em determinados caracteres pode ser problemática. Para ajudar, Raku permite {...}blocos de código no domínio de substituição, de modo que a substituição acima possa ser escrita {"\$$0"}(ou seja, uma string interpolada). Muito útil para realizar operações matemáticas simples (somas, etc.) na saída.

    Entrada de amostra:

    This is a line with <VARIABLE1>@<VARIABLE2>.
    This is a line with <VARIABLE3>.
    This is a line with <VARIABLE_UNKNOWN>.
    This is another line contains a<b.
    

    Saída de amostra:

    This is a line with $VARIABLE1@$VARIABLE2.
    This is a line with $VARIABLE3.
    This is a line with $VARIABLE_UNKNOWN.
    This is another line contains a<b.
    

    Finalmente, @terdon fornece uma excelente visão geral do problema com todos os sistemas regex, de modo que é necessário haver uma compreensão precisa do que significa digit , ou seja, são dígitos ASCII ou dígitos Unicode?

    Raku se orgulha de ser uma linguagem "pronta para Unicode", e você pode encontrar uma extensa lista de classes de caracteres Unicode para uso em regexes Raku no primeiro link na parte inferior. Conseqüentemente, em Raku, a \dabreviação de dígitos inclui dígitos Unicode. Você pode enumerar dígitos 0..9como acima ou subconjunto/restringir \ddígitos a dígitos ASCII usando a <:ASCII>classe de caracteres combinada com uma &&conjunção, como em [<:ASCII> && \d]:

    ~$ raku -pe ' s:g/ \< ( [ [<:ASCII> && \d] | <:Lu> | _ ]+ ) \> /\$$0/;'  file 
    

    Acima <:Lu>está a classe de caracteres Unicode para "Letras maiúsculas". Se desejar, o mesmo <:ASCII>truque pode ser usado para subconjunto para "Letras ASCII-maiúsculas" (ou mais simplesmente, reorganizar os colchetes acima para reagrupar).

    https://docs.raku.org/language/regexes#Unicode_properties
    https://www.unicode.org/terminology/digits.html
    https://docs.raku.org/language/regexes#Conjunction:_&&
    https:/ /docs.raku.org/linguagem/regexes
    https://raku.org

    • 0
  4. Prabhjot Singh
    2023-10-10T20:11:38+08:002023-10-10T20:11:38+08:00

    Usando gawk:

    $ awk '{print gensub(/<([[:alnum:]_]+)>/, "$\\1", "g")}' file
    # Or
    
    $ awk '{print gensub(/<(\w+)>/, "$\\1", "g")}' file
    This is a line with $VARIABLE1@$VARIABLE2.
    This is a line with $VARIABLE3.
    This is a line with $VARIABLE_UNKNOWN.
    This is another line contains a<b.
    

    Na função gensub(), um subpadrão pode ser memorizado usando parênteses as captured groupe referido a ele posteriormente com um backreferenceas \n.

    Do GNU awkmanual:

    gensub() fornece um recurso adicional que não está disponível em sub() ou gsub() : a capacidade de especificar componentes de uma regexp no texto de substituição. Isso é feito usando parênteses na regexp para marcar os componentes e depois especificando '\N' no texto de substituição, onde N é um dígito de 1 a 9.

    • 0

relate perguntas

  • Grep para um conjunto de linhas de $START a $END AND que contém uma correspondência em $MIDDLE

  • Reorganize as letras e compare duas palavras

  • Subtraindo a mesma coluna entre duas linhas no awk

  • Embaralhamento de arquivo de várias linhas

  • como posso alterar o caso do caractere (de baixo para cima e vice-versa)? ao mesmo tempo [duplicado]

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Possível firmware ausente /lib/firmware/i915/* para o módulo i915

    • 3 respostas
  • Marko Smith

    Falha ao buscar o repositório de backports jessie

    • 4 respostas
  • Marko Smith

    Como exportar uma chave privada GPG e uma chave pública para um arquivo

    • 4 respostas
  • Marko Smith

    Como podemos executar um comando armazenado em uma variável?

    • 5 respostas
  • Marko Smith

    Como configurar o systemd-resolved e o systemd-networkd para usar o servidor DNS local para resolver domínios locais e o servidor DNS remoto para domínios remotos?

    • 3 respostas
  • Marko Smith

    apt-get update error no Kali Linux após a atualização do dist [duplicado]

    • 2 respostas
  • Marko Smith

    Como ver as últimas linhas x do log de serviço systemctl

    • 5 respostas
  • Marko Smith

    Nano - pule para o final do arquivo

    • 8 respostas
  • Marko Smith

    erro grub: você precisa carregar o kernel primeiro

    • 4 respostas
  • Marko Smith

    Como baixar o pacote não instalá-lo com o comando apt-get?

    • 7 respostas
  • Martin Hope
    user12345 Falha ao buscar o repositório de backports jessie 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl Por que a maioria dos exemplos do systemd contém WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky Como exportar uma chave privada GPG e uma chave pública para um arquivo 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll status systemctl mostra: "Estado: degradado" 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim Como podemos executar um comando armazenado em uma variável? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S Por que /dev/null é um arquivo? Por que sua função não é implementada como um programa simples? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 Como ver as últimas linhas x do log de serviço systemctl 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - pule para o final do arquivo 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla Por que verdadeiro e falso são tão grandes? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis Substitua a string em um arquivo de texto enorme (70 GB), uma linha 2017-12-30 06:58:33 +0800 CST

Hot tag

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve