Substituindo substring no arquivo a com string no arquivo b quando uma correspondência é encontrada

2

Eu tenho 2 arquivos.

Arquivo 1

This is a string = mystringrocks
This is another string = mystringrocksmore

Arquivo 2

Trying to figure out: This is a string
Still trying to figure it out: This is another string

Saída desejada:

Trying to figure out: mystringrocks
Still trying to figure it out: mystringrocksmore

Eu tentei várias coisas, a mais recente delas é carregar os dois arquivos em uma matriz e fazer um loop com sed.

#!/bin/bash    
declare -a a
readarray a <filea.txt
echo $a

declare -a b
readarray b <fileb.txt
echo $b

for line in 'fileb.txt';
 do sed -i -- 's/$line/$a/' file.txt 
 done

Sem sucesso.

    
por Jeff Carson 20.09.2016 / 16:01

3 respostas

4

Você pode usar sed para criar um script sed do arquivo1 e, em seguida, executar sed com esse script para transformar o arquivo2 na saída esperada:

sed 's!^!s/!;s! = !/!;s!$!/!' file1 | sed -f- file2

A primeira saída de sed é

s/This is a string/mystringrocks/
s/This is another string/mystringrocksmore/

Que claramente executa as substituições que você precisa.

Você também pode usar o perl, ele funcionará mesmo para strings que contenham barras e pontos de exclamação:

perl -wE 'while (<>) {
              chomp;
              ($from, $to) = split / = /;
              $h{$from} = $to;
              last if eof;
          }
          $regex = join "|", map quotemeta, keys %h;
          s/($regex)/$h{$1}/, print while <>
         ' file1 file2

Ele lê o primeiro arquivo, divide cada linha em = e armazena o par $from => $to em um hash. Em seguida, ele cria uma regex de todas as chaves (ou seja, de) e passa sobre o segundo arquivo e substitui as correspondências pelos valores armazenados no hash. Também costuma-se classificar as chaves por comprimento para usar a sequência mais longa, se houver dois padrões que iniciem no mesmo local:

map quotemeta, sort { length $b <=> length $a } keys %h;
    
por 20.09.2016 / 16:07
3

Se a saída puder ser mixada (não mantenha a ordem das linhas originais), você pode usar join

join -o 2.1,1.2 -2 2 -t':' \
    <(sed 's/^/ /;s/ =/:/' File1 |sort -t: -k1,1)\
    <(sort -t: -k2 File2)
    
por 20.09.2016 / 16:29
1

Se você não tivesse escolhido diferentes separadores (: versus =) para os dois arquivos, teria sido uma tarefa de pesquisa bastante padrão usando uma matriz associativa em awk

Se você tiver a variedade GNU de awk , você pode alterar os separadores entre os arquivos usando uma regra ENDFILE , permitindo que você faça

gawk 'BEGIN{FS=" = "} NR==FNR {a[$1]=$2;next} ENDFILE{FS=": "; OFS=FS;} {print $1, a[$2]}' file1 file2
Trying to figure out: mystringrocks
Still trying to figure it out: mystringrocksmore
    
por 20.09.2016 / 16:46