Como evitar substitutos redundantes em sed?

0

1º arquivo contém:

#. This is the file name to process: waveheight.txt
#. This is the latest data to process if exists: waveheightNew.txt
 FilNam=Project2128/Input/waveheightNew.txt
 if [[ ! -f ${FilNam} ]]; then FilNam=Project2128/Input/waveheight.txt; fi

2º arquivo contém:

#. This is the file name to process: waveheightBin.txt
#. This is the latest data to process if exists: waveheightNewBin.txt
 FilNam=Project2128/Input/waveheightNewBin.txt
 if [[ ! -f ${FilNam} ]]; then FilNam=Project2128/Input/waveheightBin.txt; fi

Agora preciso processar os arquivos alterando .txt para Bin.txt ? Usar sed "s/.txt/Bin.txt/" levará a BinBin.txt para o segundo arquivo. Por sed "s/Bin.txt/.txt/" e, em seguida, sed "s/.txt/Bin.txt/" parece estranho.

Seria mais inteligente ignorar as correspondências indesejadas?

    
por MathArt 19.09.2018 / 08:56

4 respostas

3

Você pode incluir o Bin no texto para substituir, o que resultaria na substituição por ele mesmo:

sed 's/\(Bin\)\{0,1\}\.txt/Bin.txt/g'

Ou se o seu sed suportar EREs com -E (ou -r para algumas versões mais antigas do GNU ou busybox sed ):

sed -E 's/(Bin)?\.txt/Bin.txt/g'

Tenha em atenção que . é um operador regexp que corresponde a qualquer caractere único. Você precisa de \. para corresponder a um literal ponto .

    
por 19.09.2018 / 09:17
2

Você pode usar uma aparência negativa de perl para corresponder a .txt , mas apenas não é Bin.txt .

perl -pe 's/(?<!Bin)\.txt/Bin.txt/g'

Portanto, para testar:

$ echo 'Bin.txt foo.txt' | perl -pe 's/(?<!Bin)\.txt/Bin.txt/g'
Bin.txt fooBin.txt

Infelizmente, sed não oferece este constructo.

    
por 19.09.2018 / 09:14
1

Você pode fazer uma substituição condicional com sed , por exemplo, você pode testar se a linha já contém Bin.txt e somente realizar a substituição se isso não acontecer.

sed '/Bin\.txt/!s/\.txt/Bin.txt/'

Isso pressupõe que só haverá necessidade de uma substituição por linha.

Você também pode fazer a substituição incondicionalmente, e então corrigi-la se deu errado, como você sugeriu na pergunta, mas na mesma chamada para sed :

sed -e 's/\.txt/Bin.txt/' -e 's/BinBin/Bin/'
    
por 19.09.2018 / 09:10
0

Você pode fazer isso com GNU-sed , conforme mostrado:

echo "$Filnam" |\
sed -e '
   s/\.txt/\n&/;T   # try to place a newline marker to the left of .txt, quit if unsuccessful
   s/Bin\n/Bin/;t   # If the marker turned out to be just to the right of Bin => Bin.txt already 
                    # existed in the name, so we needn"t do anything n take away the marker n quit
   s/\n/Bin/        # Bin could not be found adjacent to .txt so put it n take away the marker as well
'

### Below is the POSIX sed code for accomplishing the same:
sed -e '
    s/\.txt/\
&/;/\n/!b
    s/Bin\n/Bin/;/\n/!b
    s/\n/Bin/
'
    
por 20.09.2018 / 06:56

Tags