Como posso substituir um literal \ n por um caractere de nova linha? (no OS X) [duplicado]

1

Eu tenho um script que extrai algo do meu histórico de shell e o salva em um arquivo, mas se houver uma nova linha na entrada do histórico, ele será retornado para mim com um literal \n em vez do caractere de nova linha. Gostaria de substituir o \n por uma nova linha antes de salvá-lo no arquivo.

Eu estou no OS X, e imaginei que o problema poderia ser o sed baseado no BSD que vem com o OS X (que sempre parece ser o problema quando sed não está se comportando!)  então eu tentei com gsed , e o que estava falhando com sed funcionou na primeira tentativa com gsed :

history -1 | awk '{$1=""; print}' | gsed -e 's/^[[:space:]]*//' -e s/'\n'/"\n"/

Mas, se possível, eu gostaria de algo que funcione com os utilitários padrão (seja sed ou outra coisa) no Linux ou OS X, já que não posso contar com gsed sendo instalado OS X, e como o GNU sed é o% normalsed para o Linux, obviamente não há necessidade de gsed .

    
por iconoclast 21.11.2015 / 03:16

1 resposta

1
sed 's/\\/& /g;s/\n/\
/g;  s/\\ /\\/g' <in >out

... deve manipular as substituições de ewline \n sem interpretar erroneamente escapes de barra invertida - assim você ainda pode ter uma entrada literal \n in. Estou um pouco confuso sobre como você pode obter um \n de seus comandos de histórico, no entanto.

Eu tentei w / zsh para descobrir como um \n ewline pode ser lido do arquivo de histórico sem ter escapado assim:

echo '
\n'
history -1
11355 echo '\n\n'

Isso não serve. Então, tentei isso:

hist(){ ! cat "$1"; }
echo '
\n'
FCEDIT=hist fc -1
echo '
\n'

... então provavelmente é isso que você deveria estar fazendo

Por algum motivo, zsh escapes \n ewlines em history or fc -l output de uma maneira ambígua, mas quando passa um comando de histórico para algum editor, ele dá a realidade.

O meio principal de zsh do history é fc , e o comando history não é muito mais do que um alias para fc -l . Quando fc é chamado com a opção -l , ele listará as linhas do histórico correspondente para stdout (depois de escapar ambiguamente de qualquer caractere não imprimível) , mas o comportamento padrão de fc é invocar outro utilitário com um ou mais argumentos de arquivo temporário nos quais ele gravou todas as correspondências de histórico para seus argumentos.

fc deriva o nome do utilitário que invoca da variável de ambiente $FCEDIT ou, se não estiver definido ou nulo, de $EDITOR ou, se não for bem-sucedido, será padronizado como vi . Se o utilitário chamado retornar true, fc tentará executar os comandos encontrados nos arquivos temporários editados (presumivelmente) antes de removê-los.

E assim a seqüência de comandos acima substitui cat para qualquer comando editor e inverte seu retorno para que uma leitura bem-sucedida dos arquivos temporários fc retorne false - para evitar que fc tente executar os comandos novamente .

Uma solução alternativa mais completa, que não precisa chamar um utilitário externo, seria:

history()
        case    $1      in
        (*/*) ! while   [ -r "$1" ]
                do      while   read -rE RTN
                        do :;   done    <$1
                shift;  done;;
        (*)     local   RTN=1  IFS=
                FCEDIT=history fc "$@"
                return  $((RTN*$?))
        esac

... que deve manipular quase transparentemente qualquer lista de argumentos que você possa esperar que o comando zsh ' history faça; exceto que sua saída é sempre literal e nunca inclui registros de data e hora do histórico ou números de eventos na saída (a menos que você chame como history -l [args] , caso em que se comportará como history ) .

    
por 21.11.2015 / 04:09