O que esse comando sed significa?

Oct 16 2020

Alguém pode me ajudar a interpretar o seguinte comando Linux Sed?

 sed -i '' 's#__OPENGL_LIBS__#-lGL -lGLU#' src/qt-mbgrdviz-3/qt-mbgrdviz-3.pro

Eu admito alegremente que acho a sintaxe do comando sed muito obscura, e ler a página de manual do sed não me ajudou muito até agora. Quando executo o comando acima, recebo este erro:

sed: can't read s#__OPENGL_LIBS__#-lGL -lGLU#: No such file or directory

Obviamente, o sed interpreta o terceiro argumento como um nome de arquivo - este é o arquivo a ser modificado? Na página de manual do sed, vejo que -Isignifica editar o arquivo de destino no local.

O segundo argumento é a string vazia ""- a página do manual diz que isso é "script-only-if-nenhum-outro-script", mas não explica o que isso significa. O último argumento src/qt-mbgrdviz-3/qt-mbgrdviz-3.pro- eu sei que um líder s/significa localizar e substituir, mas o que src/significa?

Respostas

2 Giacomo1968 Oct 16 2020 at 09:10

src/é apenas o diretório onde qt-mbgrdviz-3/qt-mbgrdviz-3.prodeveria estar.

O comando Sed é bastante simples, mas - como a maioria das coisas de linha de comando - pode parecer mais complicado do que é.

sed -i "" "s#__OPENGL_LIBS__#-lGL -lGLU#" src/qt-mbgrdviz-3/qt-mbgrdviz-3.pro
  • -i: Significa executar o comando em arquivos no local; significando apenas substituí-lo.
  • "": Seria a extensão de arquivo a ser usada ao fazer a edição local para backups. Mas, como diz a página do manual, “Se uma extensão de comprimento zero for fornecida, nenhum backup será salvo.” Isso basicamente implica que tudo o que segue o -Inão é opcional. Portanto, o ""valor efetivamente anula para uma extensão de comprimento zero para que os backups não sejam mais salvos. Observe que é assim que ele é usado no BSD (e macOS) e não nas ferramentas GNU usadas pelo Linux; nesse caso, -isó seria suficiente.
  • "s#__OPENGL_LIBS__#-lGL -lGLU#": No Sed, tudo o que segue o primeiro sno padrão é usado como um delimitador. Nesse caso, ele substituirá qualquer / todas as ocorrências de __OPENGL_LIBS__pelo valor de -lGL -lGLU.
  • src/qt-mbgrdviz-3/qt-mbgrdviz-3.pro: Este é simplesmente o caminho completo para o arquivo a ser sedado. Então, quando você quer src/dizer, é simplesmente o caminho do diretório que deve conter qt-mbgrdviz-3/qt-mbgrdviz-3.pro.

Observe que, embora esse comando funcione na versão BSD do Sed que está instalado em sistemas como o macOS, ele falhará em sistemas GNU devido ao -i "". Em sistemas GNU que -i ""devem ser simplesmente -iassim:

sed -i "s#__OPENGL_LIBS__#-lGL -lGLU#" src/qt-mbgrdviz-3/qt-mbgrdviz-3.pro

Saber que parece que seu erro é tentar executar aquela variante BSD do comando com GNU. Veja o erro:

sed: can't read s#__OPENGL_LIBS__#-lGL -lGLU#: No such file or directory

Com esse estranho "", o Sed no GNU interpretaria isso ""como o comando Sed e pensaria que esse "s#__OPENGL_LIBS__#-lGL -lGLU#"é o caminho do arquivo.


Extra : Nos comentários você pergunta:

“Alguém sabe a melhor forma de escrever um autoscript portátil que usa Sed?”

Não sei os detalhes de seu script ou seus objetivos, mas em meus próprios scripts Bash - que desenvolvo no macOS e uso em sistemas Linux também, tenho um pedaço de código como este próximo ao topo do roteiro:

#!/bin/bash -l

################################################################################
# Set script variables based on OS specific values.
if [[ "$OSTYPE" =~ ^darwin ]]; then
  # For macOS
  sed_options='-i ""';
else
  # For Linux
  sed_options='-i';
fi

E então - novamente usando seu comando de exemplo - eu faria algo assim:

sed ${sed_options} "s#__OPENGL_LIBS__#-lGL -lGLU#" src/qt-mbgrdviz-3/qt-mbgrdviz-3.pro

Observe como substituí -i ""/ -ipor ${sed_options}. Dessa forma, posso me concentrar na codificação do script principal quando codifico no macOS e não preciso me preocupar com problemas em sistemas Linux.