xargs o comando funciona no Ubuntu, mas não no Mac

4

Eu tenho a seguinte linha de código que uso para atualizar minha variável de data pessoal em meus projetos para a data atual de hoje. Esta linha funciona no terminal do Ubuntu, mas o terminal Mac parece estar muito atrasado. Infelizmente, copiei este snippet de algum site, por isso não sei ao certo como funciona. Sugestões?

grep -ilr --exclude=revar.sh --exclude=README.md "[DATE]" * |
    grep -v .git | xargs -i@ sed -i "s/\[DATE\]/${today}/g" @
    
por Corey hart 17.04.2010 / 23:12

5 respostas

4

Como isso funciona exatamente

  1. Gere uma lista de nomes de arquivos:

    grep -ilr --exclude=revar.sh --exclude=README.md "[DATE]" *
    

    Pesquise recursivamente (-r) para arquivos e liste (-l) os nomes daqueles em que o conteúdo do arquivo corresponde insensivelmente a maiúsculas e minúsculas (-i) a regex '[DATE]' (o que significa que o arquivo contém qualquer um dos 8 caracteres "AaDdEeTt"); exclua os nomes revar.sh e README.md e

  2. Remova quaisquer nomes de arquivos da lista que contenham um caractere seguido por 'git' (assim o nome do arquivo 'agitator' será removido):

    grep -v .git
    
  3. Processe os arquivos um de cada vez, aplicando um script 'sed' específico ao arquivo. Na notação moderna (POSIX - e MacOS X e Linux, AIX, HP-UX, Solaris, etc):

    xargs -I@ sed -i "s/\[DATE\]/${today}/g" @
    

    A opção '-i' para 'sed' significa sobrescrever o (s) arquivo (s) de entrada após o processamento. Esta é uma extensão GNU e BSD para 'sed' não especificada no padrão POSIX.

O que é implausível nisso

Esse script pode ser criticado em vários níveis.

  • A primeira string de pesquisa está incorreta; deve ter barras invertidas antes dos colchetes; a maioria dos arquivos contém pelo menos uma das letras 'dateDATE'.
  • O segundo grep é presumivelmente destinado a remover qualquer coisa sob os diretórios '.git' e precisa ser corrigido.
  • O comando 'sed' não faz distinção entre maiúsculas e minúsculas ao procurar por '[DATE]', diferente do primeiro 'grep'.

Como corrigir isso

Então, uma das duas alternativas faz sentido.

Ou:

grep -ilr --exclude=revar.sh --exclude=README.md "\[DATE\]" * |
grep -v '\.git/' |
xargs sed -i "s/\[[Dd][Aa][Tt][Ee]\]/${today}/g"

Ou:

grep -lr --exclude=revar.sh --exclude=README.md "\[DATE\]" * |
grep -v '\.git/' |
xargs sed -i "s/\[DATE\]/${today}/g"

Como o Donal Fellows observou, não há necessidade neste contexto de usar a opção '-i' ou '-I' para 'xargs'.

É útil mesmo quando corrigido?

Isso me deixa intrigado sobre como isso é útil. No primeiro dia, todas as ocorrências de '[DATE]' são mapeadas para '2010-04-17'; o que acontece no dia seguinte? Como você desmapear as datas antes de confirmar o repositório git?

Ainda assim, pelo menos você já sabe o que faz e como faz isso.

    
por 18.04.2010 / 00:15
6

O BSD xargs não tem -i , e essa opção está obsoleta no GNU xargs (quando este guia foi escrito? 1995?). Use -I em vez disso.

    
por 17.04.2010 / 23:15
3

A opção -i para xargs nunca é necessária quando o local para realizar a substituição está no final da string; é aí que os nomes dos arquivos seriam colocados de qualquer maneira. E o BSD xargs (que é o que o OSX fornece) também não suporta essa opção. Então tente isto:

grep -ilr --exclude=revar.sh --exclude=README.md "[DATE]" * |
    grep -v .git | xargs sed -i "s/\[DATE\]/${today}/g"
    
por 18.04.2010 / 00:05
1

Quanto ao sinalizador -i para sedar no Mac OS X para editar arquivos no local, você precisa adicionar uma string vazia como argumento:

sed -i "" 's/regex/replace/g' file

sed -i "" 's/regex/'"${var}"'/g' file   # create sed expression using string concatenation
    
por 18.04.2010 / 09:22
0

Usando a expansão de parâmetros Bash, você também pode evitar problemas de formatação de sed quase automagicamente:

# some basic Bash parameter expansion examples to play with
var='ddd/abc/ddd'
var="$(date)"
var=$'\\n'

echo abc | sed 's/b/'"${var}"'/g'
echo abc | sed 's/b/'"${var//\//\/}"'/g'
    
por 18.04.2010 / 09:50

Tags