ShellScript/Sed apresentando erro

Olá a todos,

Preciso de ajuda com uma shell que estou fazendo. Tenho um arquivo de texto onde estão dados como Código de um produto, Nome, e uma descrição, e outro arquivo de texto onde tenho todos os códigos.

Estou tentando criar uma shell que ira correr este arquivo com os dados do produto procurando pelo nome e alterando pelo código que está no txt separado deixando o arquivo com os dados assim, Código produto, Código de controle, descrição.
O código está assim:

$dir_dados="/home/shell/produtos/dados"
$dir_result="/home/shell/produtos/result"

while IFS= read -r line
    do
        txt_cod=$(echo "$line" | cut -b 1-6)
        txt_dados=$(cat $dir_dados/dados.txt | grep $txt_cod | cut -b 8-34)
        sed -e "s#$txt_dados#$txt_cod#" $dir_dados/dados.txt >> $dir_result/resultado.txt        
    done < codigos.txt

Mas na hora que rodo a shell ela dá o erro:

sed: -e expressão #1, caractere 29: comando `s' não terminado

Já procurei soluções e me falaram que o problema poderia ser o delimitador que estava usando no sed e por isso mudei para “#”, mas o erro continua.

Alguém poderia me ajudar, Obrigado.

Tenta

sed -i "s/$txt_dados/$txt_cod/g" "$dir_dados/dados.txt" >> "$dir_result/resultado.txt"

Mostrou o seguinte erro.

sed: -e expressão #1, caractere 29: comando `s' não terminado
sed: -e expressão #1, caractere 29: comando `s' não terminado
sed: -e expressão #1, caractere 29: comando `s' não terminado
sed: -e expressão #1, caractere 29: comando `s' não terminado
sed: -e expressão #1, caractere 25: opção desconhecida para o comando `s' (s///?)
sed: -e expressão #1, caractere 25: opção desconhecida para o comando `s' (s///?)
sed: -e expressão #1, caractere 24: opção desconhecida para o comando `s' (s///?)
sed: -e expressão #1, caractere 13: opção desconhecida para o comando `s' (s///?)
sed: -e expressão #1, caractere 19: opção desconhecida para o comando `s' (s///?)
sed: -e expressão #1, caractere 29: comando `s' não terminado
sed: -e expressão #1, caractere 29: comando `s' não terminado
sed: -e expressão #1, caractere 29: comando `s' não terminado
sed: -e expressão #1, caractere 29: comando `s' não terminado
sed: -e expressão #1, caractere 23: opção desconhecida para o comando `s' (s///?)
sed: -e expressão #1, caractere 29: comando `s' não terminado
sed: -e expressão #1, caractere 18: opção desconhecida para o comando `s' (s///?)
sed: -e expressão #1, caractere 16: opção desconhecida para o comando `s' (s///?)
sed: -e expressão #1, caractere 29: comando `s' não terminado
sed: -e expressão #1, caractere 29: comando `s' não terminado
sed: -e expressão #1, caractere 29: comando `s' não terminado
sed: -e expressão #1, caractere 29: comando `s' não terminado
sed: -e expressão #1, caractere 29: comando `s' não terminado
sed: -e expressão #1, caractere 29: comando `s' não terminado
sed: -e expressão #1, caractere 29: comando `s' não terminado
sed: -e expressão #1, caractere 29: comando `s' não terminado
sed: -e expressão #1, caractere 29: comando `s' não terminado
sed: -e expressão #1, caractere 29: comando `s' não terminado
sed: -e expressão #1, caractere 29: comando `s' não terminado
sed: -e expressão #1, caractere 29: comando `s' não terminado
sed: -e expressão #1, caractere 29: comando `s' não terminado
sed: -e expressão #1, caractere 29: comando `s' não terminado
sed: -e expressão #1, caractere 24: opção desconhecida para o comando `s' (s///?)
sed: -e expressão #1, caractere 24: opção desconhecida para o comando `s' (s///?)
sed: -e expressão #1, caractere 29: comando `s' não terminado
sed: -e expressão #1, caractere 29: comando `s' não terminado
sed: -e expressão #1, caractere 29: comando `s' não terminado
sed: -e expressão #1, caractere 29: comando `s' não terminado
sed: -e expressão #1, caractere 29: comando `s' não terminado
sed: -e expressão #1, caractere 29: comando `s' não terminado
sed: -e expressão #1, caractere 29: comando `s' não terminado
sed: -e expressão #1, caractere 24: opção desconhecida para o comando `s' (s///?)
sed: -e expressão #1, caractere 24: opção desconhecida para o comando `s' (s///?)
sed: -e expressão #1, caractere 29: comando `s' não terminado
sed: -e expressão #1, caractere 29: comando `s' não terminado
sed: -e expressão #1, caractere 29: comando `s' não terminado
sed: -e expressão #1, caractere 29: comando `s' não terminado
sed: -e expressão #1, caractere 29: comando `s' não terminado
sed: -e expressão #1, caractere 29: comando `s' não terminado
sed: -e expressão #1, caractere 29: comando `s' não terminado
sed: -e expressão #1, caractere 29: comando `s' não terminado
sed: -e expressão #1, caractere 24: opção desconhecida para o comando `s' (s///?)
sed: -e expressão #1, caractere 24: opção desconhecida para o comando `s' (s///?)
sed: -e expressão #1, caractere 29: comando `s' não terminado
sed: -e expressão #1, caractere 29: comando `s' não terminado
sed: -e expressão #1, caractere 24: opção desconhecida para o comando `s' (s///?)
sed: -e expressão #1, caractere 29: comando `s' não terminado
sed: -e expressão #1, caractere 25: opção desconhecida para o comando `s' (s///?)
sed: -e expressão #1, caractere 29: comando `s' não terminado
sed: -e expressão #1, caractere 29: comando `s' não terminado
sed: -e expressão #1, caractere 29: comando `s' não terminado
sed: -e expressão #1, caractere 29: comando `s' não terminado
sed: -e expressão #1, caractere 29: comando `s' não terminado
sed: -e expressão #1, caractere 24: opção desconhecida para o comando `s' (s///?)
sed: -e expressão #1, caractere 29: comando `s' não terminado
sed: -e expressão #1, caractere 24: opção desconhecida para o comando `s' (s///?)
sed: -e expressão #1, caractere 29: comando `s' não terminado
sed: -e expressão #1, caractere 24: opção desconhecida para o comando `s' (s///?)
sed: -e expressão #1, caractere 24: opção desconhecida para o comando `s' (s///?)
sed: -e expressão #1, caractere 29: comando `s' não terminado
sed: -e expressão #1, caractere 24: opção desconhecida para o comando `s' (s///?)
sed: -e expressão #1, caractere 29: comando `s' não terminado
sed: -e expressão #1, caractere 29: comando `s' não terminado

@Capezotte @Deleterium convoco os universitários

1 curtida

Só pra vocês entenderem como esta os arquivos txt, o dados.txt está assim:
*a primeira linha com os títulos não tem no arquivo coloquei só pra ilustrar.

ID       Nome              Descrição
001    NOTEBOOK    Chromebook Samsung 11.6' 

Alguns nomes tem o “/” para separar nas descrição, por isso mudei o delimitador. O arquivo codigos.txt está assim:

0001010010606    Chromebook 

Se não funciona para nenhuma linha, não sei…

Se funcionar para algumas linhas e outras não, pode ser que seja problema de escape de caracteres.

Eu faria um debug:

set -x

$dir_dados="/home/shell/produtos/dados"
$dir_result="/home/shell/produtos/result"

while IFS= read -r line
    do
        txt_cod=$(echo "$line" | cut -b 1-6)
        txt_dados=$(cat $dir_dados/dados.txt | grep $txt_cod | cut -b 8-34)
        sed -e "s#$txt_dados#$txt_cod#" $dir_dados/dados.txt >> $dir_result/resultado.txt
        sleep 1
    done < codigos.txt

Assim vc consegue ver a linha que está sendo executada. Se der erro, control+c e examina a linha se está conforme planejado.

2 curtidas

Já tentou separar com um delimitador que você provavelmente não usaria em nenhum dos campos? Tipo ; ou |.
Por exemplo:

001|NOTEBOOK|Chromebook Samsung 11.6'

Não criei script mas consegui pegar os campos usando o cat e cut. Sei que está tentando com o sed, mas estou te sugerindo uma alternativa, caso seja viável para você.

Veja abaixo as saídas dos comandos no meu terminal:

╭─    /tmp ········································ ✔  19:51:49  ─╮
╰─ echo "001|NOTEBOOK|Chromebook Samsung 11.6'" > ./arquivo

╭─    /tmp ········································ ✔  19:52:03  ─╮
╰─ cat arquivo | cut -d"|" -f1
001

╭─    /tmp ········································ ✔  19:52:13  ─╮
╰─ cat arquivo | cut -d"|" -f2
NOTEBOOK

╭─    /tmp ········································ ✔  19:52:18  ─╮
╰─ cat arquivo | cut -d"|" -f3
Chromebook Samsung 11.6'
1 curtida

Talvez você já tenha percebido e corrigido isso no seu lado, mas em shell uma variável é obtida com $VAR, mas o valor só pode ser dado com VAR=1

VAR=notas.txt # certo
sed 's/a/b/g' "$VAR"

$VAR=notas.txt # errado
sed 's/a/b/g' "$VAR" # vai dar arquivo ou diretório inexistente

Recomendo fortemente postar os resultados da sugestão do @Deleterium (cabeçalho com set -x) aqui, pois poderemos ver cada linha do seu script sendo executada em tempo real. Me parece que alguns produtos tem ; no nome (a explicação que eu consigo pensar).

Enquanto um log mais detalhado da solução com base no sed não vem, gostaria de propor um processamento por awk.

Solução sem sed

Acho que esse meu código vai ter algumas limitações já que os nomes do codigos.txt não estão exatamente iguais ao dados.txt. Tive que usar um codigos.txt que dizia exatamente Chromebook Samsung 11.6'. Porém, já é uma base para abordar o problema de uma maneira diferente.

Enfim, há introduções ao Awk pela net melhores das que cabem nesse post, mas vai aqui um exemplo:

#!/usr/bin/awk -f
BEGIN {
	FS="  +" # separar entradas na tabela com pelo menos dois espaços (para não acidentalmente pegar espaços nos nomes dos produtos)
	OFS="  " # separar entras na saída com dois espaços (assim a saída pode ser reutilizada)
}

# Script está processando o arquivos de dados (que ou é "codigos.txt" sozinho, ou um caminho que termina com "/codigos.txt")
FILENAME ~ "(^|/)codigos.txt$" {
	codigo[$2] = $1 # o código associado ao produto ($2º item da tabela) é o $1º item da tabela
}

# padrão semelhante ao acima, mas para o dados.txt
FILENAME ~ "(^|/)dados.txt" {
	# trocar o código original (1º campo) pelo código vindo do códigos.txt
	# usar o terceiro campo como nome do produto.
	$1 = codigo[$3]
	# Exibir linha modificada.
	print
}

Salve como produtos.awk, marque como executável (assim como faria com um shell script) e rode
./produtos.awk /caminho/codigos.txt /caminho/dados.txt

(os códigos tem que vir antes na linha de comando, se não a array codigo estará vazia quando o dados.txt for processado).

Exemplo:

$ cat codigos.txt
0001010010606    Chromebook Samsung 11.6'
$ cat dados.txt
001    NOTEBOOK    Chromebook Samsung 11.6'
$ ./produto.awk /caminho/codigos.txt /caminho/dados.txt
0001010010606  NOTEBOOK  Chromebook Samsung 11.6'

A saída que aparece no terminal pode ser salva num arquivo de resultados com ./produto.awk /caminho/codigos.txt /caminho/dados.txt > /caminho/resultado

2 curtidas