Eu não analisei o seu script, mas vejo alguns lugares em que você está passando por problemas de citação (caracteres que têm um significado especial quando você não quer que eles sejam):
-
read -d $'\n' LINE
(uma maneira complicada de escrever read LINE
) analisa falhas de barra invertida, portanto, ele efetivamente come barras invertidas. Torne read -r LINE
. Esse comando também desativa espaços iniciais e finais; para evitar isso, torne-o IFS= read -r LINE
.
- Você está substituindo variáveis em scripts sed. O conteúdo dessas variáveis é analisado como um script sed, não uma sequência de pesquisa ou texto de substituição da maneira que você pretende. Este é o problema com
?
no arquivo: quando aparece em $TARGET
, sed vê um ?
. Para corrigir isso, adicione caracteres de barra invertida antes de todos os caracteres que são especiais em sed (e tenha cuidado que em um regexp e em um texto de substituição, você precisa escapar de diferentes caracteres!).
Na verdade ... não faça o que escrevi acima. Eu estava apenas explicando o que deu errado; mas você deve reescrever completamente o seu roteiro, porque você está usando uma chave de fenda para martelar um prego.
Você está usando o bash, que possui matrizes associativas. Usar variáveis com um nome construído é uma invasão conveniente quando nada melhor está disponível, mas é mais difícil de usar do que uma estrutura de dados adequada. A menos que as variáveis XX_yahoo
realmente venham do ambiente, use uma matriz associativa.
typeset -A targets
targets[yahoo]='www.yahoo.com'
Enquanto é possível analisar um arquivo linha por linha no shell com while read …
, não é realmente apropriado para arquivos grandes (é lento) ou arquivos com sintaxe não trivial (como você descobriu, é difícil analisar as coisas corretamente quando você está indo e voltando entre o shell e ferramentas externas como sed). Sua tarefa é um material básico para um script awk (ou perl, como mostrado em outras respostas).
E se você for usar o awk de qualquer maneira, é melhor definir o array associativo diretamente no awk.
Código não testado.
#!/bin/awk -f
BEGIN {
targets[yahoo]="www.yahoo.com";
targets[google]="www.google.com";
}
function MakeTitleCase(text) {
split(text, words);
text = "";
for (w in words) {
text = text toupper(substr(w,1,1)) substr(w,2)
}
return text;
}
/^ *\MakeLink\[[^][{}]*\]{}/ {
target_start = index($0, "[") + 1;
target_end = index($0, "]") - 1;
target = substr($0, target_start, target_end - target_start);
if (target in targets) {
replacement = targets[target];
} else {
replacement = MakeTitleCase(target);
}
$0 = substr($0, 1, target_start-1) replacement substr($0, target_end);
}
1