Eu tenho uma situação em que quero que um script bash substitua uma linha inteira em um arquivo. O número da linha é sempre o mesmo, de modo que pode ser uma variável codificada.
Não estou tentando substituir uma sub-string nessa linha, só quero substituir essa linha por uma nova.
Existem métodos bash para fazer isso (ou algo simples que possa ser lançado em um script .sh).
sed: -e expression #1, char 26: unknown option to ``s'
e minha linha é:sed -i '7s/.*/<param-value>http://localhost:8080/ASDF/services/REWS.REWSHttpSoap12Endpoint/</param-value>/' $TCE_SVN_HOME\trunk\tce\EWC\WebContent\WEB-INF\web.xml
. Qualquer ideia?/
no texto de substituição seria interpretado como a barra final dos
comando, a menos que escapasse (\/
). A coisa mais fácil, porém, é escolher um caractere diferente e não utilizado como delimitador. Por exemplosed -i '7s{.*}{<param-value>http://...}' $TCE_SVN_HOME/trunk...
,.s
determina o delimitador. Então, para mudar o seu comando para usar, por exemplo, o#
que seria assim:sed -i '7s#.*#<param-value>http://localhost:8080/ASDF/services/REWS.REWSHttpSoap12Endpoint/</param-value>#'
-e
if-i
também. assim, o comando correto se torna:sed -e 'Ns/.*/replacement-line/' -i '' file.txt
Na verdade, eu usei esse script para substituir uma linha de código no arquivo cron nos servidores UNIX da nossa empresa há algum tempo. Nós o executamos como um shell script normal e não tivemos problemas:
Isso não passa pelo número da linha, mas você pode alternar facilmente para um sistema baseado em número de linha colocando o número da linha antes do
s/
e colocando um curinga no lugar dethe_original_line
.fonte
sed -e "s/.../.../" /dir/file > /dir/temp_file
sed -e "s/.../.../" /dir/file > /dir/file
Vamos supor que você queira substituir a linha 4 pelo texto "diferente". Você pode usar o AWK assim:
O AWK considera a entrada como "registros" divididos em "campos". Por padrão, uma linha é um registro.
NR
é o número de registros vistos.$0
representa o registro completo atual (enquanto$1
é o primeiro campo do registro e assim por diante; por padrão, os campos são palavras da linha).Portanto, se o número da linha atual for 4, imprima a string "diferente", mas imprima a linha inalterada.
No AWK, o código do programa incluído
{ }
é executado uma vez em cada registro de entrada.Você precisa citar o programa AWK entre aspas simples para impedir que o shell tente interpretar coisas como o
$0
.EDIT: Um programa AWK mais curto e mais elegante da @chepner nos comentários abaixo:
Somente para o registro (ou seja, linha) número 4, substitua o registro inteiro pela string "diferente". Em seguida, para cada registro de entrada, imprima o registro.
Claramente, minhas habilidades no AWK estão enferrujadas! Obrigado, @chepner.
EDIT: e veja também uma versão ainda mais curta de @Dennis Williamson:
Como isso funciona é explicado nos comentários: o
1
sempre avalia true, portanto, o bloco de código associado sempre é executado. Mas não há nenhum bloco de código associado, o que significa que o AWK faz sua ação padrão de apenas imprimir a linha inteira. O AWK foi projetado para permitir programas concisos como este.fonte
awk 'NR==4 {$0="different"} { print }' input_file.txt
.awk 'NR==4 {$0="different"}1' input_file.txt
1
faz? (Nota: Eu testei e realmente funciona Eu só não entendo como!.)Dado este arquivo de teste (test.txt)
o comando a seguir substituirá a primeira linha por "texto de nova linha"
Resultado:
Mais informações podem ser encontradas aqui
http://www.thegeekstuff.com/2009/11/unix-sed-tutorial-append-insert-replace-and-count-file-lines/
fonte
sed '1 cnewline text' test.txt
faria isso também.no bash, substitua N, M pelos números de linha e xxx yyy pelo que você deseja
EDITAR
De fato, nesta solução, existem alguns problemas, com os caracteres "\ 0" "\ t" e "\"
"\ t", pode ser resolvido colocando IFS = antes da leitura: "\", no final da linha com -r
mas para "\ 0", a variável está truncada, não há uma solução no bash puro: atribua string contendo caracteres nulos (\ 0) a uma variável no Bash Mas no arquivo de texto normal não há caracteres nulos \ 0
perl seria uma escolha melhor
fonte
fonte
Excelente resposta da Chepner. Ele está trabalhando para mim no bash Shell.
aqui
index
- Linha nãonewLine
- nova string de linha que queremos substituir.Da mesma forma, o código abaixo é usado para ler uma linha específica no arquivo. Isso não afetará o arquivo real.
here
!d
- excluirá as linhas que não sejam a linha no.$index
Portanto, obteremos a saída como string de linha$index
no no arquivo.fonte
${newline}
?No mac eu usei
fonte
Você pode até passar parâmetros para o comando sed:
test.sh
orignial output.dat:
A execução de ./test.sh fornece o novo output.dat
fonte
line=5; sed -i "${line}s/.*/replaced by '$i'!/" output.dat