2016-10-31 2 views
2

Ich habe eine CSV-Datei mit 7 Spalten und ich bin nur an der Änderung der ersten Spalte interessiert. Tatsächlich erscheint in einigen Zeilen ein Zeilenname n mal in verketteter Weise ohne Leerzeichen. Ich brauche ein Skript, das den Beginn der Duplizierung erkennt und alle Duplikate entfernt.BASH: Split-Strings ohne Trennzeichen und behalten nur erste Teilzeichenfolge

Beispiel eines Zeilennamen unter anderem:

Row name = EXAMPLE1.ABC_DEF.panel4EXAMPLE1.ABC_DEF.panel4EXAMPLE1.ABC_DEF.panel4

ersetzen durch: EXAMPLE1.ABC_DEF.panel4

In den verschiedenen Reihen:

  • n kann variieren

  • Die Länge des Zeilennamen

  • Die Struktur des Zeilennamen kann variieren (zB kann variieren. Menge an _ und .), aber es ist immer ohne Raum

zusammengestellt Was ich versucht habe:

:%s/(.+)\1+/\1/ 

Schritt-für-Schritt:

  • %s : ersetzen Sie in der ganzen Datei

  • (.+)\1+: Erste Erfassungsgruppe. .+ entspricht einem beliebigen Zeichen (mit Ausnahme von Leitungsabschlüssen), + ist der Quantifizierer - Übereinstimmungen zwischen einem und unbegrenzten Zeiten, so oft wie möglich, nach Bedarf zurückgeben.

  • \1+: stimmt mit dem gleichen Text wie zuletzt durch die erste abgestimmte Gruppe

  • Ersatz von \1

Erfassung erhalte ich die folgenden Fehler jedoch:

  • E65: Unzulässige Rückreferenz

  • E476 0
  • : ungültiger Befehl

+0

Was das Werkzeug, das diese gibt, ist Fehler? Der Befehl, den Sie gepostet haben, entspricht dem, was Sie erwarten, wenn Sie mit sed arbeiten: 'sed -E/(. +) \ 1 +/\ 1/'file' – oliv

+0

@oliv Sieht aus wie vi/Vim? –

+0

Sie müssen entkommen: ':% s/\ (. \ + \) \ 1 \ +/\ 1 /' –

Antwort

0

Von dem, was ich verstehe, was Sie brauchen nur eine Zeile enthalten EXAMPLE1.ABC_DEF.panel4.In diesem Fall können Sie wie folgt vorgehen:

Entfernen Sie zuerst Duplikate in einer Zeile:

sed -i "s/EXAMPLE1.ABC_DEF.panel4.*/EXAMPLE1.ABC_DEF.panel4/g" 

Dann duplizierte Linien entfernen:

awk '!a[$0]++' 
+0

Vielen Dank @Nasr für Ihre Antwort. Aber das ist nicht genau das, wonach ich gesucht habe. Die CSV-Datei enthält Zeilen mit unterschiedlichen Zeilennamen. Ich versuche also, alle Zeilen umzubenennen, in denen der Name doppelt vorhanden ist. Ich hoffe es ist diesmal besser erklärt. – Svalf

0

Wenn alle Reihen des Formats sind gab Ihnen in die Frage (wie EXAMPLExyzEXAMPLExyz), dann sollte dieses Werk

awk -F"EXAMPLE" '{print FS $2}' file 

diese „Beispiel nimmt "als Feldbegrenzer und fordert ihn auf, nur die erste 'Spalte' zu drucken. Es wird "EXAMPLE" zu dieser ersten Spalte vorangestellt (durch Aufruf der eingebauten awk Variablen FS). Danke, @andlrc.

Keine ideale Lösung, aber möglicherweise gut genug für diesen Zweck.

+0

Ich denke, eine Multicar als Feldtrennzeichen ist eine GNU-Erweiterung. Sie können die Variable 'FS' verwenden, um das Umschreiben' BEISPIEL' zu vermeiden: '... print FS $ 2 ...' – andlrc

+0

@andlrc, danke, ich habe diesen Vorschlag implementiert. – VM17

0

Dieses Skript, mit dem ersten arg ist die Zeichenfolge, zu testen, kann das größte doppelte String abrufen (dh „totototo“ done „toto“, nicht „zu“)

#!/usr/bin/env bash 
row_name="$1" 
#test duplicate from the longest to the smallest, by how many we need to split the string ? 
for ((i=2; i<${#row_name}; i++)) 
do 
    match="True" 
    #continue test only if it's mathematically possible 
    if ((${#row_name} % i)); then 
    continue 
    fi 
    #length of the potential duplicate substring 
    len_sub=$((${#row_name}/i)) 
    #test if the first substring is equal to each others 
    for ((s=1; s<i; s++)) 
    do 
    if ! [ "${row_name:0:${len_sub}}" = "${row_name:$((len_sub * s)):${len_sub}}" ]; then 
     match="False" 
     break 
    fi 
    done 
    #each substring are equal, so return string without duplicate 
    if [ $match = "True" ]; then 
    row_name="${row_name:0:${len_sub}}" 
    break 
    fi 
done 
echo "$row_name" 
Verwandte Themen