# [bash] Suchen/Ersetzen via Dictionary File?

## 3PO

Hallo Zusammen,

ich habe folgendes Problem:

Ich habe eine Datei, die so aussieht:

```
foo bar

123 987

alt neu

asdf ASDF
```

Nun sollen via bash in der Datei blabla.txt alle foo, durch bar, alle 123, durch 987, usw. ersetzt werden.

Leider habe fehlt mir im Moment eine Idee, wie ich das am besten realisieren könnte?

Evtl. hat ja Jemand eine Idee?   :Smile: 

----------

## Finswimmer

Schleife über die Dictionary Datei.

Pro Zeile trennst nach Leerzeichen: 1. Teil ist $search, 2. Teil $replace

Dann per sed s'#$search#$replace#'g  die gesamte blabla Datei ersetzen.

----------

## 3PO

Ich habe es jetzt mal "quick'n'dirty" so gelöst:

```
#!/bin/bash

INFILE="dictionary.txt"

TARGET="my_file.txt"

cat $INFILE |while read i ; do

  SEARCH=${i%%\ *} 

  i=${i#*\ } 

  REPLACE=${i%%\ *} 

  sed -i $TARGET -e "s/$SEARCH/$REPLACE/" 

done
```

Geht sicherlich auch eleganter, aber so funktioniert es erst mal.  :Wink: 

----------

## mv

Deutlich eleganter:

```
INFILE=dictionary.txt

TARGET=my_file.txt

while read SEARCH REPLACE

do sed -i -e "s'$SEARCH'$REPLACE'g" -- "$TARGET"

done <"$INFILE"
```

In beiden Fällen musst Du darauf achten, dass die letzte Zeile von dictionary.txt mit einem "newline" abgeschlossen wird, sonst schlägt das "while" zu früh fehl...

----------

## 3PO

Man könnte ja zur Sicherheit noch ein,

```
echo /n >> $INFILE
```

einbauen.  :Wink: 

----------

## mv

 *3PO wrote:*   

> Man könnte ja zur Sicherheit noch ein,
> 
> ```
> echo /n >> $INFILE
> ```
> ...

 

Und das Source-File modifizieren? Sehr schlechter Stil. Was ich meinte wäre ein besserer Test im Stile von 

```
while {

  read SOURCE DEST

  [ -n "${DEST}" ]

}

do ...

done <...
```

----------

## papahuhn

Das Problem an den Lösungen hier ist, dass bereits ersetzte Strings in einem weiteren Schleifendurchlauf nochmal ersetzt werden könnten. Beispiel:

```

foo bar

bar bier

```

soll angewendet werden auf den Text "Hello foobar". Was will man da als Resultat bekommen? "Hello barbier" oder "Hello bierbier"? In den Fällen, in denen ich solche Ersetzungen machen musste, war immer das Resultat "Hello barbier" gefordert. Das Vorgehen dazu ist dann, dass man nach "foo|bar" matcht und dann im Regex-Replace-Part einen Hash-Lookup macht. Wie das mit bash/sed ginge, weiss ich nicht, für Perl macht man das exemplarisch so:

```

#!/usr/bin/perl -w

use strict;                                                                   

my $str = 'Hello foobar';

my %hash = map {split /\s+/} <DATA>;

my $rx = join '|', keys %hash;

$str =~ s/($rx)/$hash{$1}/eg;

print $str;

__DATA__

foo bar

bar bier

```

----------

