Como o sed pode variar entre as plataformas (em particular, BSD / MacOSX versus Linux), pode ser útil especificar a plataforma na qual você está usando o sed.
Isaac
sed "s / (. *) / # \ 1 /" $ nome do arquivo | tr '#' '\ t'> $ sedTmpFile && mv $ sedTmpFile $ filename.
user2432405
Para usuários do OS X (macOS), consulte esta pergunta .
Ah sim; para esclarecer: nem todas as versões do sed entendem \tna parte de substituição da expressão (ele reconheceu \tna parte de correspondência de padrão muito bem)
John Weldon
3
awwwwwwwwwwwwwwwwwwwww, ok, isso é muito interessante. E estranho. Por que você o faria reconhecê-lo em um lugar, mas não no outro ...?
sixtyfootersdude,
2
Chamado de um script, isso não funcionará: as guias seriam ignoradas por sh. Por exemplo, o seguinte código de um script de shell adicionará $ TEXT_TO_ADD, sem precedê-lo por uma tabulação: sed "$ {LINE} a \\ $ TEXT_TO_ADD" $ FILE.
Você estava no caminho certo com a $'string'explicação, mas falta. Na verdade, eu suspeito que, devido ao uso extremamente estranho, você provavelmente tem um entendimento incompleto (como a maioria de nós faz com o bash). Veja minha explicação abaixo: stackoverflow.com/a/43190120/117471
Bruno Bronosky
1
Lembre-se de que o BASH não expande variáveis como $TABaspas simples, portanto, você precisará usá-lo com aspas duplas.
nealmcb
Cuidado ao usar *aspas duplas ... isso será tratado como um glob, não como a regex que você pretende.
levigroker
27
@sedit estava no caminho certo, mas é um pouco estranho definir uma variável.
Solução (específico do bash)
A maneira de fazer isso no bash é colocar um cifrão antes da string entre aspas simples.
$ echo -e '1\n2\n3'123
$ echo -e '1\n2\n3'| sed 's/.*/\t&/g'
t1
t2
t3
$ echo -e '1\n2\n3'| sed $'s/.*/\t&/g'123
Se sua string precisa incluir expansão de variável, você pode colocar strings entre aspas assim:
$ timestamp=$(date +%s)
$ echo -e '1\n2\n3'| sed "s/.*/$timestamp"$'\t&/g'149123795811491237958214912379583
Palavras da forma $ 'string' são tratadas de maneira especial. A palavra se expande para string , com caracteres de escape de barra invertida substituídos conforme especificado pelo padrão ANSI C. Seqüências de escape de barra invertida, se presentes, são decodificadas ...
O resultado expandido é entre aspas simples, como se o cifrão não estivesse presente.
Solução (se você deve evitar bash)
Eu pessoalmente acho que a maioria dos esforços para evitar o bash são tolos porque evitar o bash NÃO * torna seu código portátil. (Seu código será menos frágil se você explicá-lo do bash -euque se você tentar evitar bash e usar sh[a menos que você seja um ninja POSIX absoluto].) Mas, em vez de ter um argumento religioso sobre isso, vou apenas dar-lhe o MELHOR * responda.
$ echo -e '1\n2\n3'| sed "s/.*/$(printf '\t')&/g"123
* Melhor resposta? Sim, porque um exemplo do que a maioria dos scripts de shell anti-bash faria de errado em seu código é usar echo '\t'como na resposta de @robrecord . Isso funcionará com o GNU echo, mas não com o BSD echo. Isso é explicado pelo The Open Group em http://pubs.opengroup.org/onlinepubs/9699919799/utilities/echo.html#tag_20_37_16 E este é um exemplo de por que tentar evitar bashismos geralmente falham.
É engraçado que você esteja usando um recurso específico do "GNU echo" (interpretando \ t como um caractere de tabulação) para resolver um bug específico do "sed BSD" (interpretando \ t como 2 caracteres separados). Presumivelmente, se você tiver "GNU echo", também terá "GNU sed". Nesse caso, você não precisaria usar o eco. Com BSD echo echo '\t'vai produzir 2 caracteres separados. A maneira portátil POSIX é usar printf '\t'. É por isso que digo: não tente tornar seu código portátil não usando o bash. É mais difícil do que você pensa. Usar bashé a coisa mais portátil que a maioria de nós pode fazer.
Bruno Bronosky,
3
Você não precisa usar sedpara fazer uma substituição quando, na verdade, deseja apenas inserir uma guia na frente da linha. A substituição desta caixa é uma operação cara em comparação com apenas imprimi-la, especialmente quando você está trabalhando com arquivos grandes. É mais fácil de ler também, pois não é regex.
sednão suporta \t, nem outras sequências de escape como \npara esse assunto. A única maneira que descobri de fazer isso foi realmente inserir o caractere de tabulação no script usando sed.
Dito isso, você pode querer considerar o uso de Perl ou Python. Aqui está um pequeno script Python que escrevi e uso para todas as expressões regulares de fluxo:
Eu acho que os outros ter esclarecido este adequadamente para outras abordagens ( sed, AWK, etc.). No entanto, bashseguem minhas respostas específicas (testadas no macOS High Sierra e CentOS 6/7).
1) Se o OP quiser usar um método de pesquisa e substituição semelhante ao que propôs originalmente, eu sugeriria o uso perlpara isso, como segue. Notas: barras invertidas antes dos parênteses para regex não devem ser necessárias, e esta linha de código reflete como $1é melhor usar do que \1com o perloperador de substituição (por exemplo, por documentação do Perl 5 ).
2) No entanto, como apontado por ghostdog74 , uma vez que a operação desejada é simplesmente adicionar uma guia no início de cada linha antes de alterar o arquivo tmp para o arquivo de entrada / destino ( $filename), recomendo perlnovamente, mas com a seguinte modificação (s):
3) Claro, o arquivo tmp é supérfluo , então é melhor apenas fazer tudo 'no lugar' (adicionando -isinalizador) e simplificar as coisas para uma linha mais elegante com
Respostas:
Nem todas as versões de
sed
entendem\t
. Basta inserir uma guia literal (pressione Ctrl- e Vdepois Tab).fonte
\t
na parte de substituição da expressão (ele reconheceu\t
na parte de correspondência de padrão muito bem)Usando o Bash, você pode inserir um caractere TAB programaticamente, assim:
fonte
$'string'
explicação, mas falta. Na verdade, eu suspeito que, devido ao uso extremamente estranho, você provavelmente tem um entendimento incompleto (como a maioria de nós faz com o bash). Veja minha explicação abaixo: stackoverflow.com/a/43190120/117471$TAB
aspas simples, portanto, você precisará usá-lo com aspas duplas.*
aspas duplas ... isso será tratado como um glob, não como a regex que você pretende.@sedit estava no caminho certo, mas é um pouco estranho definir uma variável.
Solução (específico do bash)
A maneira de fazer isso no bash é colocar um cifrão antes da string entre aspas simples.
Se sua string precisa incluir expansão de variável, você pode colocar strings entre aspas assim:
Explicação
Em bash
$'string'
causa "expansão ANSI-C". E é isso que a maioria de nós esperar quando usamos coisas como\t
,\r
,\n
, etc. De: https://www.gnu.org/software/bash/manual/html_node/ANSI_002dC-Quoting.html#ANSI_002dC-QuotingSolução (se você deve evitar bash)
Eu pessoalmente acho que a maioria dos esforços para evitar o bash são tolos porque evitar o bash NÃO * torna seu código portátil. (Seu código será menos frágil se você explicá-lo do
bash -eu
que se você tentar evitar bash e usarsh
[a menos que você seja um ninja POSIX absoluto].) Mas, em vez de ter um argumento religioso sobre isso, vou apenas dar-lhe o MELHOR * responda.* Melhor resposta? Sim, porque um exemplo do que a maioria dos scripts de shell anti-bash faria de errado em seu código é usar
echo '\t'
como na resposta de @robrecord . Isso funcionará com o GNU echo, mas não com o BSD echo. Isso é explicado pelo The Open Group em http://pubs.opengroup.org/onlinepubs/9699919799/utilities/echo.html#tag_20_37_16 E este é um exemplo de por que tentar evitar bashismos geralmente falham.fonte
Usei algo assim com um shell Bash no Ubuntu 12.04 (LTS):
Para anexar uma nova linha com tab, segundo quando a primeira é correspondida:
Para substituir a primeira pela guia, a segunda :
fonte
\\t
e não\t
.Use
$(echo '\t')
. Você precisará de aspas em torno do padrão.Por exemplo. Para remover uma guia:
fonte
echo '\t'
vai produzir 2 caracteres separados. A maneira portátil POSIX é usarprintf '\t'
. É por isso que digo: não tente tornar seu código portátil não usando o bash. É mais difícil do que você pensa. Usarbash
é a coisa mais portátil que a maioria de nós pode fazer.Você não precisa usar
sed
para fazer uma substituição quando, na verdade, deseja apenas inserir uma guia na frente da linha. A substituição desta caixa é uma operação cara em comparação com apenas imprimi-la, especialmente quando você está trabalhando com arquivos grandes. É mais fácil de ler também, pois não é regex.por exemplo, usando awk
fonte
Usei no Mac:
Usei este link para referência
fonte
sed
não suporta\t
, nem outras sequências de escape como\n
para esse assunto. A única maneira que descobri de fazer isso foi realmente inserir o caractere de tabulação no script usandosed
.Dito isso, você pode querer considerar o uso de Perl ou Python. Aqui está um pequeno script Python que escrevi e uso para todas as expressões regulares de fluxo:
fonte
Em vez de BSD sed, eu uso perl:
fonte
Eu acho que os outros ter esclarecido este adequadamente para outras abordagens (
sed
,AWK
, etc.). No entanto,bash
seguem minhas respostas específicas (testadas no macOS High Sierra e CentOS 6/7).1) Se o OP quiser usar um método de pesquisa e substituição semelhante ao que propôs originalmente, eu sugeriria o uso
perl
para isso, como segue. Notas: barras invertidas antes dos parênteses para regex não devem ser necessárias, e esta linha de código reflete como$1
é melhor usar do que\1
com operl
operador de substituição (por exemplo, por documentação do Perl 5 ).2) No entanto, como apontado por ghostdog74 , uma vez que a operação desejada é simplesmente adicionar uma guia no início de cada linha antes de alterar o arquivo tmp para o arquivo de entrada / destino (
$filename
), recomendoperl
novamente, mas com a seguinte modificação (s):3) Claro, o arquivo tmp é supérfluo , então é melhor apenas fazer tudo 'no lugar' (adicionando
-i
sinalizador) e simplificar as coisas para uma linha mais elegante comfonte