ubuntuusers.de

Bedingte Veränderung einzelner Dateizeilen

Status: Gelöst | Ubuntu-Version: Ubuntu 8.10 (Intrepid Ibex)
Antworten |

xJulian

Anmeldungsdatum:
23. Dezember 2007

Beiträge: 6

Hallo!

Folgende Situation:

Gegeben sind zwei Dateien, a.txt und b.txt. Jede Zeile in a.txt ist auch in b.txt enthalten, jedoch nicht umgekehrt. Beispiel:

a.txt:

hallo
welt

b.txt:

viel
inhalt
hallo
noch
mehr
welt
dinge

Was ich letztendlich will, ist, dass b.txt komplett ausgegeben wird, aber dass dabei genau die Zeilen, die in a.txt enthalten sind, entweder fett oder in Großbuchstaben angezeigt werden (je nachdem, ob eine bestimmte Variable auf 1 gesetzt ist). Mir würde also im Prinzip ein Mechanismus reichen, der alle Zeilen von b.txt ausgibt, aber nur die entsprechenden Zeilen aus a.txt erst noch mit einem von mir angegebenen sed-Aufruf bearbeitet.

Wie würdet ihr an dieses Problem herangehen?

Edit: Hätte vielleicht noch erwähnen sollen, dass das ganze in ein Bash-Skript eingebunden werden soll. Also, falls das aus der Fragestellung nicht klar wird. ☺

Clythos

Anmeldungsdatum:
15. Mai 2006

Beiträge: Zähle...

Ganz einfach:

diff -u a.txt b.txt

"-" davor, Zeile ist nur in der ersten Datei " " (Leerzeichen) ist in beiden "+" ist nur in der zweiten Datei

Kuehly

Anmeldungsdatum:
15. Oktober 2006

Beiträge: 282

Oder komplizierter mit Bash-Skript:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
#!/bin/bash

if ! [ "$#" = "2" ]; then
    echo "Usage: $0 DATEI1 DATEI2"
    exit 1
fi

for line in `cat $2`; do
    if [[ `cat $1` == *$line* ]]; then
        # Die Zeile ist in beiden Dateien. Die folgende Ausgabe kann verändert werden.
        echo "> $line"
    else
        echo $line
    fi
done

exit 0

Gruß, Jan

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17596

Wohnort: Berlin

1
2
3
sed 's#^#s/\\(#;s#$#\\)/<b>\\1<\\/b>/#' a.txt > a.sed 
sed -f a.sed b.txt
 

Resultat:

viel
inhalt
<b>hallo</b>
noch
mehr
<b>welt</b>
dinge

xJulian

(Themenstarter)

Anmeldungsdatum:
23. Dezember 2007

Beiträge: 6

Ihr seid ja der Wahnsinn. Danke!

Der Vollständigkeit halber:

user unknown schrieb:

1
2
3
sed 's#^#s/\\(#;s#$#\\)/<b>\\1<\\\/b>/#' a.txt > a.sed 
sed -f a.sed b.txt
 

Anscheinend frisst das Forum bei der Darstellung Backslashes, so dass die sed-Kommandos in der Datei a.sed nicht vollständig sind. Das korrekte Skript sieht so aus:

1
2
3
sed 's#^#s/\\\(#;s#$#\\\)/<b>\\\1<\\\/b>/#' a.txt > a.sed 
sed -f a.sed b.txt
 

Damit funktioniert alles. Die anderen Varianten hab ich jetzt noch nicht getestet.

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17596

Wohnort: Berlin

Es hat, glaube ich, noch einen kleinen Fehler.

Fügt man

  • ohallo

  • halloa

in b.txt ein, kommt er zum Vorschwein. So müßte es klappen:

s#^\(.*\)$#s/^\1$/<b>\1<\\/b>/#

in eine Datei einfetten.sed speichern, und mit

1
sed -f einfetten.sed a.txt > a.sed && sed -f a.sed b.txt

ausführen. Um die Backslashes in richtiger Zahl zu übernehmen den Beitrag zitieren, und den Quellcode übernehmen.

phst

Anmeldungsdatum:
24. Juni 2007

Beiträge: 527

Die Bash-Lösung ist natürlich sehr listig. Hier zur Vollständigkeit noch eine Python-Lösung:

1
2
3
4
5
6
7
8
#!/usr/bin/python2.5
a = frozenset(line.strip() for line in open("a.txt"))
for line in open("b.txt"):
  line = line.strip()
  if line in a:
    print "<b>%s</b>" % line
  else:
    print line

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17596

Wohnort: Berlin

phst schrieb:

Die Bash-Lösung ist natürlich sehr listig.

Danke, daß das jmd. mitbekommen hat. ☺ Der Sed-Ausdruck ist ja bemerkenswert kryptisch, die Ratio Lesbares/Sonderzeichen denkbar gering, wobei das lesbare ausgerechnet <b> und </b> ist, und ergo nicht lesbar aussieht. ☺ Ich nenne Sed auch eine Einwegsprache: Man kann es manchmal schreiben, aber oft nicht lesen. 😉

Antworten |