Estou usando o Arch, que foi atualizado há algumas semanas. Os pacotes usados são
- Arch 6.0.10-arch2-1
- BASH 5.1.16(1)-lançamento
- gnu sed 4.9
- gnu grep 3.8
- openbox 3.6.1
Dentro do meu arquivo de texto Openbox, rc.xml
tenho duas linhas da seguinte maneira
<!-- <keybind key="Right"> -->
<keybind key="s-Up">
Desejo alternar/trocar frequentemente as duas linhas acima pelas duas linhas abaixo usando um script
<!-- <keybind key="s-Up"> -->
<keybind key="Right">
Isso me permite alterar rapidamente uma combinação de teclas sem editar tediosamente meu arquivo de texto de configuração de combinações de teclas ( rc.xml
) todas as vezes.
O script que tenho até agora está abaixo e não está funcionando, embora eu saiba que está próximo.
Não estou muito preocupado com a forma como essa alternância é alcançada, mas já tendo gasto uma quantidade significativa de tempo nisso, seria bom colocar o script abaixo funcionando.
As sed
expressões abaixo fazem o trabalho de troca de texto como deveriam.
A if
instrução parece fazer a primeira sed
troca se a condição for atendida, mas não a segunda sed
troca se a condição não for atendida, que é o problema.
var_a=""
#var_a=$(grep -zoP "<\!\-\- <keybind key=\"Right\"> \-\->\n\n<keybind key=\"s-Up\">" /home/kes/Dropbox/lubuntu-rc.xml | sed ':a;N;$!ba;s|\n\n||g')
var_a=$(grep -zoP "<\!\-\- <keybind key=\"Right\"> \-\->\n\n<keybind key=\"s-Up\">" /home/kes/Dropbox/lubuntu-rc.xml | tr -d '\n' )
# result of grep is
# <!-- <keybind key="Right"> --><keybind key="s-Up">
echo $var_a; sleep 0.5
#if [[ -z ! "$var_a" ];then
if [[ '$var_a'=='<!-- <keybind key="Right"> --><keybind key="s-Up">' ]]; then
sed -ie ':a;N;$!ba;s|<!-- <keybind key="Right"> -->\n\n<keybind key="s-Up">|<!-- <keybind key="s-Up"> -->\n\n<keybind key="Right">|g' /home/kes/Dropbox/lubuntu-rc.xml
else
sed -ie ':a;N;$!ba;s|<!-- <keybind key="s-Up"> -->\n\n<keybind key="Right">|<!-- <keybind key="Right"> -->\n\n<keybind key="s-Up">|g' /home/kes/Dropbox/lubuntu-rc.xml
fi
Na verdade, a condição nunca será atendida, porque as aspas simples
'$var_a'
impedirão que sua variável seja expandida, portanto, a string literal$var_a
nunca será igual à outra string literal.Use aspas duplas e deve funcionar, mas gostaria de acrescentar algumas observações sobre seu script:
(1) Você primeiro faz um
grep
, depois baseia uma condição no conteúdo que obtém dissogrep
e, finalmente, usa doissed
scripts diferentes. Isso provavelmente resultará em erros. Na verdade, vocêsed
fará tudo sozinho:Se foi feita a primeira substituição, o
t
pula para o final do script, caso contrário é realizada a outra substituição. Ogrep
eif
já está incluído!(2) Sua forma de coletar todas as linhas
:a;N;$!ba
só funcionará no GNUsed
, porque de acordo com o padrão POSIX, tudo depois dos dois pontos será a marca de salto, sem exceção para;
. Não há problema para você, porque você tem GNUsed
, mas também tem a-z
opção de processar o arquivo do furo em uma execução sem a peça. Se você gosta dele portátil,H;1h;$!d;x
faça o mesmo através do espaço de espera.(3) Acho que a
g
bandeira lobal é supérflua, porque essas linhas existem apenas uma vez, correto?(4) Escrever a mesma coisa repetidamente pode causar erros e é mais difícil de ler. Por que não reutilizar uma parte marcando-a com
\(\)
e referindo-se a ela como\1
?(5) Na verdade, você não precisa processar o arquivo inteiro como um só (isso pode até causar overruns para arquivos grandes), você só precisa processar a cada três linhas consecutivas juntas, usando o esquema (geralmente duas linhas juntas
N;P;D
,1N
somando expanda para três linhas):Provavelmente, seria possível simplificar ainda mais, mas isso exigiria informações adicionais sobre o conteúdo do arquivo.
Supondo que o documento XML esteja bem formado e sintaticamente correto, você pode usar o processador XML
xmlstarlet
para alternar os valores.Ignorando o XML comentado no documento, o seguinte consegue isso alterando primeiro todos os
key
atributos de cadakeybind
nó do valorRight
paratemporary
(atributos com outro valor não serão afetados). Em seguida, ele altera o mesmo atributo des-Up
paraRight
e, finalmente, detemporary
paras-Up
. A stringtemporary
é uma string arbitrária que não é usada para okey
atributo dokeybind
nó.Isso efetivamente troca os valores de
Right
paras-Up
e vice-versa.Isso transformaria um documento como
... em
Se você inserir
--inplace
logo após aedit
palavra na linha de comando, a edição será feita no local, modificando o arquivo original.