Tag,
also wie man das in der zsh realisiert weiß ich nicht. (ich hab hier nichtmal die zsh installiert...)
Beispieldatei
So wie ich dich verstanden habe ist eine Beispieldatei z.B:
A1-B1-C1
A2-B2-C2
A3-B3-C3
A4-B2-C3
A4-B4-C5
A2-B6-C3
A7-B3-C3
A8-B2-C1
Vorgehen
Aber ich hab das ganze mal in bash geschrieben.
Vom Prinzip her gibt es drei schritte: (vom prinzip her, das was du in Java machen würdest)
- Datei L einlesen ( jede Zeile entspricht einem Element in dem array $lines bzw dessen B entspricht einem Element im array $Bs )
- Die Indizes von mehrfach-vorkommenden Bs in einen Array ( $duplicateBs ) und die einmal-vorkommenden Bs in einen anderen Array ( $uniqueBs )
- Zuerst die Zeilen der Datei ( Elemente in $lines ) ausgeben lassen, deren Zeilennummern ( = indizes) in $uniqueBs vorkommen, und dann die Zeilen mit den Nummern in $uniqueBs
Bashscript
Mein Bashscripts (benötigte Befehle: bash, [, echo, seq, cat, true, false :lol: ) schaut so aus:
#!/bin/bash
file="$1"
# DEBUG=true -> print additional info to stderr
export DEBUG=false # is true or false
function getElementCount()
{
# $1 = element to count
# ${*:2} = all elements after parameter $1 are array to check
count="0"
for i in ${*:2} ; do
if [ "$i" = "$1" ] ; then
# element is found
# so increase counter
count=$[$count+1]
fi
done
echo "$count"
$DEBUG && echo "$count of $1 in ${*:2}" >&2
}
function findBs()
{
lines=() # buffer of all lines
Bs=() # plural of B ;-)
# Step 1: read file to $lines
linenr="0" # number of current line
while read LINE ; do
# LINE has format: A-B-C
# A, B, C must not contain -
#save line for later
lines[$linenr]="${LINE}"
# get B of this line
curB=${LINE%-*} # remove "-C"
curB=${curB#*-} # remove "A-"
Bs[$linenr]="$curB"
# read to "next line"
linenr=$[$linenr+1]
done
# Step 2: find duplicates / unique Bs
duplicateBs=() # index of duplicates
uniqueBs=() # index of unique Bs
# find duplicate and uniq indexes in Bs
for i in $(seq 0 $[${#Bs[@]}-1]) ; do
if [ $(getElementCount "${Bs[$i]}" "${Bs[@]:0}") -gt 1 ]
then # if current B is duplicated
# then add index to duplicateBs
duplicateBs[${#duplicateBs[@]}]="$i"
$DEBUG && echo "$i : $B is duplicate" >&2
else
uniqueBs[${#uniqueBs[@]}]="$i"
$DEBUG && echo "$i : $B is unique" >&2
fi
done
# Step 3: print unique Bs and then duplicates
for i in ${uniqueBs[@]} ; do
# print it to stdout , or to an outfile etc...
echo "${lines[$i]}"
done
for i in ${duplicateBs[@]} ; do
# print it to stdout , or to an outfile etc...
echo "${lines[$i]}"
done
}
cat "$1"|findBs
#
Meintest du das ?
Bzw läuft das script so, wie du dir das vorstellst ?
Temporäre Dateien
Also mein script läuft ohne temporäre Dateien, es gibt das ergebnis einfach auf die stdout aus.
Wenn du das direkt nochmal in die gleiche datei umleiten würdest, würde es NICHT funktionieren: (Es würde den kompleten inhalt der datei löschen!!)
Du müsstest also in Schritt 3 das die ausgabe der Zeilen (
echo "${lines[$i]}) in die ursprüngliche datei umleiten.
d.h. Schritt 3 sähe dann so aus:
# [...]
# Step 3: print unique Bs and then duplicates to OUTFILE
OUTFILE="L"
# clear OUTFILE
echo -n "" > $OUTFILE
for i in ${uniqueBs[@]} ; do
# print it to stdout , or to an outfile etc...
echo "${lines[$i]}" >> $OUTFILE
done
for i in ${duplicateBs[@]} ; do
# print it to stdout , or to an outfile etc...
echo "${lines[$i]}" >> $OUTFILE
done
# usw... [...]
ich wäre Jedoch dafür, das ergebnis lieber in eine zweite datei zu schreiben(Ja,.. quasi eine temporäre Datei), um das Ergebnis sicherheitshalber nocheinmal kontrolieren zu können :'D
Ergebnis
Mein Ergebnis sieht dann so aus:
A1-B1-C1
A4-B4-C5
A2-B6-C3
A2-B2-C2
A3-B3-C3
A4-B2-C3
A7-B3-C3
A8-B2-C1
viel spaß^^