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 / 701267
Accepted
Zoltan King
Zoltan King
Asked: 2022-05-04 06:04:15 +0800 CST2022-05-04 06:04:15 +0800 CST 2022-05-04 06:04:15 +0800 CST

Como posso substituir um caractere dentro de um contexto específico em cada linha de todo o arquivo?

  • 772

Eu tenho um arquivo grande que contém centenas de frases em inglês no seguinte formato:

\phrase
{.   .    .     *     *   }
{I shoul-d've stayed home.}
{aɪ ʃʊd‿əv ˈsteɪd ˈhoʊm.} <- only replace on this line

\phrase
{ .   .   *  }
{Did you eat?}
{dɪdʒjʊʷˈit? ↗} <- only replace on this line

\phrase
{ *    .  *    .    *  .  .    .     *   .  }
{Yeah, I made some pas-ta if you're hun-gry.}
{ˈjɛə, aɪ ˈmeɪd səm ˈpɑ stəʷɪf jər ˈhʌŋ gri.} <- only replace on this line

É um arquivo LaTeX .tex. Eu gostaria de substituir todos os rcaracteres em cada transcrição fonética (por transcrição fonética quero dizer cada terceira linha após a \phraselinha) pelo ɹsímbolo (código hexadecimal U+0279).

Fazer isso manualmente no Emacs é complicado para mim. Eu queria saber se existe uma maneira de direcionar essas linhas de alguma forma e fazer a substituição automaticamente.

Todos os rcaracteres devem ser substituídos por ɹ, não há exceção, mas apenas na transcrição fonética, deixe rcomo está no texto em inglês/não fonético.

É possível fazer isso de alguma forma usando um script ou algo assim? Não há quebras de linha no meu documento, então a transcrição é sempre a terceira linha após \phrase. Obrigada!

text-processing replace
  • 8 8 respostas
  • 1624 Views

8 respostas

  • Voted
  1. Archemar
    2022-05-04T06:19:01+08:002022-05-04T06:19:01+08:00

    uma versão awk (você precisará de um arquivo de retransmissão, você pode colocá-lo em uma linha)

    awk '/\\phrase/ { p=NR ; } 
         NR == p+3 { gsub("r","ɹ")  ; } 
        {print;} ' old-file.tex > new-file.tex
    

    Onde

    • /\\phrase/ { p=NR ; }será definido ppara cada número de linha onde \phraseaparecer
    • NR == p+3 { gsub("r","ɹ") ; } realizar a substituição na 3ª linha após
    • {print;}imprimir toda a linha.

    isso deu em sua amostra: (observe o ɹeplace)

    \phrase
    {.   .    .     *     *   }
    {I shoul-d've stayed home.}
    {aɪ ʃʊd‿əv ˈsteɪd ˈhoʊm.} <- only ɹeplace on this line
    
    \phrase
    { .   .   *  }
    {Did you eat?}
    {dɪdʒjʊʷˈit? ↗} <- only ɹeplace on this line
    
    \phrase
    { *    .  *    .    *  .  .    .     *   .  }
    {Yeah, I made some pas-ta if you're hun-gry.}
    {ˈjɛə, aɪ ˈmeɪd səm ˈpɑ stəʷɪf jəɹ ˈhʌŋ gɹi.} <- only ɹeplace on this line
    
    • 18
  2. thanasisp
    2022-05-04T11:23:57+08:002022-05-04T11:23:57+08:00
    awk 'c&&!--c {gsub(/r/,"ɹ")} /\\phrase/ {c=3} 1' file > newfile
    

    c&&!--cé um awkidioma comum, implementando a while getlinelógica, consulte a referência .

    A ação que segue esta condição será executada somente ao diminuir de um para zero.

    Ao combinar um literal '\phrase', definimos c=3, para gsub()que seja executado apenas na 3ª linha após a correspondência, e isso se repete para todas as correspondências.

    • 11
  3. Best Answer
    JoL
    2022-05-04T20:46:53+08:002022-05-04T20:46:53+08:00

    Já que você está no Emacs...

    O Caminho do Mal/Vim

    Se você evil-modeinstalou (ou mudou para o Vim), pode fazer isso:

    :g/^\\phrase/+3s/r/ɹ/g
    

    Isso é o mais simples.

    A maneira macro do teclado

    Ficando com o estoque do Emacs, você pode usar uma macro de teclado:C-x ( C-M-s ^\\phrase Enter C-n C-n C-n C-a C-space C-e C-M-% r Enter ɹ Enter ! C-x ) C-u 2 C-x e

    C-x (inicia a macro, C-x )finaliza a macro, C-x eexecuta a macro, C-u 2/ C-2modifica C-x epara que execute a macro 2 vezes. Você também pode usar um número grande como C-u 10000se não quiser contar. C-M-sprocura uma regex. Após descer 3 linhas e selecionar a linha, C-M-%inicia uma substituição na seleção. Após os prompts para o que substitui o quê, !significa aceitar todas as substituições na seleção.

    O Caminho da Elisp

    Você também pode abrir o *scratch*buffer e executá-lo (com C-M-xo cursor no código):

    (with-current-buffer "foo"
      (goto-char (point-min))
      (while (re-search-forward "^\\\\phrase" nil t)
        (forward-line 3)
        (replace-string-in-region "r" "ɹ" (point) (line-end-position))))
    

    onde fooé o nome do buffer onde você deseja fazer isso.

    EDIT: replace-string-in-regionfoi introduzido no Emacs 28.1 (versão mais recente até o momento da escrita). Se o seu Emacs for mais antigo, você pode usar search-forwarde replace-matchassim:

    (with-current-buffer "foo"
      (goto-char (point-min))
      (while (re-search-forward "^\\\\phrase" nil t)
        (forward-line 3)
        (while (search-forward "r" (line-end-position) t)
          (replace-match "ɹ"))))
    

    A maneira do filtro de comandos do Shell

    Você também pode filtrar o buffer do Emacs por meio de um comando externo, como uma das outras respostas aqui:C-x h C-u M-| <command> Enter

    C-x hseleciona todo o buffer. M-|solicitará o comando que filtrará a seleção. C-umodifica M-|para substituir a seleção pela saída em vez de colocá-la em um buffer temporário.

    • 9
  4. terdon
    2022-05-04T06:35:03+08:002022-05-04T06:35:03+08:00

    Se você sempre tem uma linha em branco entre cada seção, você pode tentar o modo "parágrafo" do perl para ler cada seção como uma única "linha":

    $ perl -F'\n' -00ane '$F[3]=~s/r/ɹ/g; print join "\n",@F , "\n"' file 
    \phrase
    {.   .    .     *     *   }
    {I shoul-d've stayed home.}
    {aɪ ʃʊd‿əv ˈsteɪd ˈhoʊm.} <- only ɹeplace on this line
    
    \phrase
    { .   .   *  }
    {Did you eat?}
    {dɪdʒjʊʷˈit? ↗} <- only ɹeplace on this line
    
    \phrase
    { *    .  *    .    *  .  .    .     *   .  }
    {Yeah, I made some pas-ta if you're hun-gry.}
    {ˈjɛə, aɪ ˈmeɪd səm ˈpɑ stəʷɪf jəɹ ˈhʌŋ gɹi.} <- only ɹeplace on this line
    
    

    Explicação

    • -a: divide automaticamente cada linha de entrada no array @F.

    • -F'\n': dividido em caracteres de nova linha.

    • -00: "modo de parágrafo", as linhas agora são definidas por \n\n(uma linha vazia), então cada seção se torna uma "linha".

    • -ne: leia o arquivo de entrada linha por linha e aplique o script fornecido por -ea cada linha.

    • $F[3]=~s/r/ɹ/g;: substitua all rpor ɹno 4º elemento do array @F(esta é a 4ª linha de cada seção; arrays começam em 0).

    • print join "\n",@F , "\n"': junte o @Farray modificado com \ne imprima-o junto com um extra \n.


    Se você não pode confiar nisso e precisa sempre ir para a 3ª linha após uma correspondência de linha \phrase, você pode fazer:

    $ perl -pe '$k=0 if /\\phrase\b/; $k++; s/r/ɹ/g if $k==4' file 
    \phrase
    {.   .    .     *     *   }
    {I shoul-d've stayed home.}
    {aɪ ʃʊd‿əv ˈsteɪd ˈhoʊm.} <- only ɹeplace on this line
    
    \phrase
    { .   .   *  }
    {Did you eat?}
    {dɪdʒjʊʷˈit? ↗} <- only ɹeplace on this line
    
    \phrase
    { *    .  *    .    *  .  .    .     *   .  }
    {Yeah, I made some pas-ta if you're hun-gry.}
    {ˈjɛə, aɪ ˈmeɪd səm ˈpɑ stəʷɪf jəɹ ˈhʌŋ gɹi.} <- only ɹeplace on this line
    

    Isso define um contador para 0cada vez que vemos \phrase, e o incrementa em um em cada nova linha. Então, só fazemos a substituição quando o valor do contador for 4.

    • 7
  5. Stéphane Chazelas
    2022-05-04T23:19:27+08:002022-05-04T23:19:27+08:00

    Com padrão sed:

    sed '/^\\phrase$/{n;n;n;s/r/ɹ/g;}'
    

    y/r/ɹ/no lugar de s/r/ɹ/gtambém funcionaria em implementações compatíveis com POSIX seddesde que o ɹcaractere seja considerado como um na localidade do usuário, mas s/r/ɹ/gseria mais portátil, pois também funcionaria com sedimplementações que não suportam caracteres multi-byte (como ɹem UTF-8 ; Não consigo encontrar nenhuma codificação de caracteres ondeɹ esteja codificado em um único byte).

    Para que isso ɹseja codificado corretamente na localidade do usuário, com zsh, você pode fazer:

    sed $'/^\\\\phrase$/{n;n;n;s/r/\u0279/g;}'
    

    Onde isso \u0279seria expandido para a codificação desse ɹ caractere na localidade do usuário¹


    ¹ Isso $'\uXXXX'agora é suportado por alguns outros shells, mas cuidado com o fato de que em alguns, isso é expandido na localidade como era quando o shell foi iniciado ou quando essa linha de código foi lida, não necessariamente quando a localidade em que esse sedcomando é executado . No ksh93, é sempre expandido em UTF-8, independentemente da localidade do usuário. Quando o caractere não está disponível no charset da localidade, o comportamento também varia entre os shells. Causa um erro dezsh

    • 6
  6. hobbs
    2022-05-04T21:42:25+08:002022-05-04T21:42:25+08:00
    perl -Mutf8 -CSD -pe '$phrase = $. if /\\phrase/; s/r/ɹ/g if $. == $phrase + 3'
    

    bastante direto; defina sinalizadores para manipulação de unicode, lembre-se do número da linha ( $.) se virmos \phrase, e faça uma substituição se o número da linha for três maior que isso.

    • 3
  7. roaima
    2022-05-04T07:14:58+08:002022-05-04T07:14:58+08:00

    Como estamos obtendo outras respostas, aqui está uma solução trabalhada de uma pergunta quase duplicada . Isso é para GNU sed, mas na resposta vinculada também há sugestões POSIX:

    sed '/^\\phrase/,+3 { /^\\phrase/,+2 !{ s/r/ɹ/g } }'
    

    O que isso faz é pegar o \phrase(limitado ao início da linha) e trabalhar com isso e as próximas duas linhas ( +3, começando com a linha correspondente como linha um). Para as duas primeiras linhas deste grupo não aplica a substituição de rpara ɹ(a implicação é que para a última linha do grupo aplica a substituição).

    Saída do exemplo:

    \phrase
    {.   .    .     *     *   }
    {I shoul-d've stayed home.}
    {aɪ ʃʊd‿əv ˈsteɪd ˈhoʊm.} <- only ɹeplace on this line
    
    \phrase
    { .   .   *  }
    {Did you eat?}
    {dɪdʒjʊʷˈit? ↗} <- only ɹeplace on this line
    
    \phrase
    { *    .  *    .    *  .  .    .     *   .  }
    {Yeah, I made some pas-ta if you're hun-gry.}
    {ˈjɛə, aɪ ˈmeɪd səm ˈpɑ stəʷɪf jəɹ ˈhʌŋ gɹi.} <- only ɹeplace on this line
    
    • 2
  8. jubilatious1
    2022-05-06T13:57:51+08:002022-05-06T13:57:51+08:00

    Usando Raku (anteriormente conhecido como Perl_6)

    raku -pe 'state $ph; $ph = 0 if /^ \\phrase $/; s:g/r/ɹ/ if ++$ph == 4;'  
    

    Você pode querer experimentar o Raku, já que ele foi construído desde o início para lidar com Unicode. O código acima (na verdade) é muito semelhante à resposta Perl5 postada por @hobbs, na medida em que usa os -pesinalizadores de linha de comando de impressão automática do Raku e conta as linhas a partir da linha em que \phraseé visto.

    Para o código acima, a variável $phé stated uma vez no início do programa. À medida que o arquivo é lido na linha, $phé definido para 0quando uma linha contendo \phrasee nada mais é encontrada (significado ++$ph== 1 é True). A partir deste ponto é realizado um teste de if ++$ph == 4autoincremento (contagem regressiva de 3 linhas), que se satisfeito, então direciona o operador de substituição s:g/r/ɹ/para atuar :globally dentro da linha desejada.

    • [Para os aficionados de Perl: Raku dispensa uma ampla variedade de variáveis ​​de compilador, como $.em favor do statedeclarador de variáveis ​​e variáveis ​​de estado anônimas associadas, como $, @, e %. De acordo com os documentos, " statedeclara variáveis ​​com escopo léxico, assim como my. No entanto, a inicialização acontece exatamente uma vez...". . A $variável de estado anônima no Raku pode ser usada para adicionar números de linha a um arquivo de texto, ou seja, raku -ne 'put ++$ ~ " $_";'].

    Observe que, como o Raku lida com o Unicode normalmente, a s:g/r/ɹ/substituição pode ser escrita com a mesma facilidade:

    s:g/r/\x0279/

    OU

    s:g/r/\c[Latin Small Letter Turned R]/

    ...a conversão descritiva acima "Latin Small Letter Turned R" pode ajudar quando você tiver dificuldades relacionadas a fontes/Unicode (ou... se você estiver cansado de tentar lembrar de códigos hexadecimais Unicode ).

    Saída de amostra:

    \phrase
    {.   .    .     *     *   }
    {I shoul-d've stayed home.}
    {aɪ ʃʊd‿əv ˈsteɪd ˈhoʊm.} <- only ɹeplace on this line
    
    \phrase
    { .   .   *  }
    {Did you eat?}
    {dɪdʒjʊʷˈit? ↗} <- only ɹeplace on this line
    
    \phrase
    { *    .  *    .    *  .  .    .     *   .  }
    {Yeah, I made some pas-ta if you're hun-gry.}
    {ˈjɛə, aɪ ˈmeɪd səm ˈpɑ stəʷɪf jəɹ ˈhʌŋ gɹi.} <- only ɹeplace on this line
    

    https://en.wikipedia.org/wiki/IPA_Extensions
    https://docs.raku.org/syntax/state
    https://raku.org

    • 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