Ich habe zwei Arrays wie folgt:
A=(vol-175a3b54 vol-382c477b vol-8c027acf vol-93d6fed0 vol-71600106 vol-79f7970e vol-e3d6a894 vol-d9d6a8ae vol-8dbbc2fa vol-98c2bbef vol-ae7ed9e3 vol-5540e618 vol-9e3bbed3 vol-993bbed4 vol-a83bbee5 vol-ff52deb2)
B=(vol-175a3b54 vol-e38d0c94 vol-2a19386a vol-b846c5cf vol-98c2bbef vol-7320102b vol-8f6226cc vol-27991850 vol-71600106 vol-615e1222)
Die Arrays sind nicht sortiert und enthalten möglicherweise sogar doppelte Elemente.
Ich möchte den Schnittpunkt dieser beiden Arrays erstellen und die Elemente in einem anderen Array speichern. Wie würde ich das machen?
Wie erhalte ich die Liste der Elemente, die in B angezeigt werden und in A nicht verfügbar sind?
foo
zweimal), müssen Sie sie im Ergebnis duplizieren?Antworten:
comm(1)
ist ein Tool, mit dem Sie zwei Listen vergleichen und den Schnittpunkt oder Unterschied zwischen zwei Listen ermitteln können. Die Listen müssen sortiert werden, aber das ist einfach zu erreichen.Um Ihre Arrays in eine sortierte Liste zu bringen, die geeignet ist für
comm
:Dadurch wird Array A in eine sortierte Liste umgewandelt. Machen Sie dasselbe für B.
So
comm
geben Sie die Kreuzung zurück:-1 -2
sagt, Einträge zu entfernen, die für Datei1 (A) und für Datei2 (B) eindeutig sind - der Schnittpunkt der beiden.Damit es zurückgibt, was sich in Datei2 (B) befindet, aber nicht in Datei1 (A):
-1 -3
Sagt, Einträge zu entfernen, die für Datei1 eindeutig und für beide gemeinsam sind - wobei nur die Einträge für Datei2 eindeutig bleiben.comm
Verwenden Sie zum Einspeisen von zwei Pipelines die Funktion "Substitution verarbeiten" vonbash
:So erfassen Sie dies in einem Array:
Alles zusammenfassen:
quelle
\n
.\n
versuchen Sie Folgendes:arr1=( one two three "four five\nsix\nseven" ); arr2=( ${arr1[@]:1} "four five\\nsix" ); n1=${#arr1[@]}; n2=${#arr2[@]}; arr=( ${arr1[@]/ /'-_-'} ${arr2[@]/ /'-_-'} ); arr=( $( echo "${arr[@]}"|tr '\t' '-t-'|tr '\n' '-n-'|tr '\r' '-r-' ) ); arr1=( ${arr[@]:0:${n1}} ); arr2=( ${arr[@]:${n1}:${n2}} ); unset arr; printf "%0.s-" {1..10}; printf '\n'; printf '{'; printf " \"%s\" " "${arr1[@]}"; printf '}\n'; printf "%0.s-" {1..10}; printf '\n'; printf '{'; printf " \"%s\" " "${arr2[@]}"; printf '}\n'; printf "%0.s-" {1..10}; printf '\n\n'; unset arr1; unset arr2
LC_ALL=C
. Stellen Sie stattdessenLC_COLLATE=C
den gleichen Leistungszuwachs ohne andere Nebenwirkungen ein. Um korrekte Ergebnisse zu erhalten , müssen Sie auch die gleiche Sortierung einstellen, die fürcomm
verwendet wurdesort
, z. B .:unset LC_ALL; LC_COLLATE=C ; comm -12 <(printf '%s\n' "${A[@]}" | sort) <(printf '%s\n' "${B[@]}" | sort)
Sie können alle Elemente in A und B abrufen, indem Sie beide Arrays durchlaufen und Folgendes vergleichen:
Sie können alle Elemente in B, aber nicht in A auf ähnliche Weise abrufen:
quelle
A
undB
, ist esintersections
immer das Gleiche, um neu zu ordnen?Dafür gibt es einen ziemlich eleganten und effizienten Ansatz
uniq
wir - verwenden. Wir müssen jedoch Duplikate aus jedem Array entfernen, sodass nur eindeutige Elemente übrig bleiben. Wenn Sie Duplikate speichern möchten, gibt es nur eine Möglichkeit, "beide Arrays zu durchlaufen und zu vergleichen".Stellen Sie sich vor, wir haben zwei Arrays:
Lassen Sie uns zunächst diese Arrays in Mengen umwandeln. Wir werden es tun, weil es eine mathematische Operationskreuzung gibt, die als Schnittmenge von Mengen bekannt ist, und Menge ist eine Sammlung verschiedener Objekte, verschiedene oder einzigartig . Um ehrlich zu sein, ich weiß nicht, was "Schnittmenge" ist, wenn wir über Listen oder Sequenzen sprechen. Wir können zwar eine Teilsequenz aus der Sequenz auswählen, aber diese Operation (Auswahl) hat eine etwas andere Bedeutung.
Also, lasst uns verwandeln!
Überschneidung:
Wenn Sie die Elemente in einem anderen Array speichern möchten:
uniq -d
Also zeige nur Duplikate (ich denke,uniq
ist aufgrund seiner Realisierung eher schnell: Ich denke, dass es mit erledigt istXOR
Bedienung ).Rufen Sie die Liste der Elemente ab, die in angezeigt werden
B
und in nicht verfügbar sindA
, zB\A
Oder beim Speichern in einer Variablen:
Also haben wir zuerst den Schnittpunkt von
A
undB
(das ist einfach die Menge der Duplikate zwischen ihnen), sagen wir es istA/\B
, und dann haben wir die Operation des Invertierens des Schnittpunkts vonB
undA/\B
(das ist einfach nur ein einziges Element) verwendet, also bekommen wirB\A = ! (B /\ (A/\B))
.PS
uniq
wurde von Richard M. Stallman und David MacKenzie geschrieben.quelle
Effizienz ignorieren, hier ist ein Ansatz:
quelle
Mein reiner Bash-Weg
Da diese Variablen nur enthalten ,
vol-XXX
wennXXX
eine hexadezimale Zahl ist, gibt es eine schnelle Möglichkeit , mit bash - ArraysDies muss Folgendes ausgeben:
In diesem Zustand enthält die Bash-Umgebung:
Sie könnten also:
Dies ergibt:
Dies ist aber numerisch sortiert! Wenn Sie eine Originalbestellung wünschen, können Sie:
Sie zeigen die Bände in der Reihenfolge an, in der sie eingereicht wurden:
oder
für die Anzeige nur in A :
oder auch:
wird erneut drucken :
quelle
Duplicate
Linien nutzlos sind, können sie natürlich einfach fallengelassen werden.