Corrisponde solo alla prima occorrenza in una riga con Regex


42

Sono completamente nuovo su regex e apprezzerei molto qualsiasi aiuto.

Il compito è semplice. Ho un file CSV con record che leggono in questo modo:

12345,67890,12345,67890
12345,67890,12345,67890
12345,67890,12345,67890
12345,67890,12345,67890
12345,67890,12345,67890

Vorrei sostituire la prima virgola con uno spazio e lasciare intatte le altre virgole, per ogni riga. Esiste un'espressione regex che corrisponderà solo alla prima virgola?

Ho provato questo: ^.....,. Questo corrisponde alla virgola, tuttavia, corrisponde anche all'intera lunghezza della stringa che precede la virgola, quindi se provo a sostituirlo con uno spazio vengono eliminati anche tutti i numeri.


quale strumento stai usando? (sed, perl, awk, qualcos'altro?)
Mat

Textpad (Windows)
cows_eat_hay

Risposte:


53

Il modello di corrispondenza potrebbe essere:

^([^,]+),

Questo significa

^        starts with
[^,]     anything but a comma
+        repeated one or more times (use * (means zero or more) if the first field can be empty)
([^,]+)  remember that part
,        followed by a comma

Ad esempio in perl, l'intera corrispondenza e sostituzione sarebbe simile a:

s/^([^,]+),/\1 /

La parte sostitutiva prende semplicemente tutto ciò che corrisponde e lo sostituisce con il primo blocco che hai ricordato e aggiunge uno spazio. Il coma viene "eliminato" perché non si trova nel primo gruppo di acquisizione.


Eccezionale! Grazie Mat, ha funzionato benissimo. In realtà non ha funzionato in Textpad (penso che il loro regex sia limitato), quindi ho finito per scaricare PowerGrep e ho usato la ricerca e la sostituzione con l'espressione che hai fornito e ha funzionato benissimo. Grazie anche per la bella spiegazione, aiuta a capire cosa sta succedendo.
cows_eat_hay,

7
s/,/ /

Questo, di default (cioè senza l' gopzione), sostituisce solo la prima corrispondenza.


1
Si tratta in realtà di cercare e sostituire la sintassi di Textpad?
Daniel Beck

1
Questa è una sintassi di sed, perle di alcuni altri strumenti.
pabouk,

3

Questo dovrebbe corrispondere solo il primo numero e la virgola: ^(\d{5}),. Se desideri divorare tutto il resto della linea, cambia la regex in questo:^(\d{5}),(.*)$


Anche questo ha funzionato. Alla fine ho usato la soluzione di Mat ma ho provato anche la tua e funziona. Grazie per l'aiuto!
cows_eat_hay,

Perché \d{5}e no [^,]*? Questo sarebbe almeno meno generico.
JustinCB,

2

La soluzione più elegante è usare l'abbinamento pigro:

s/^(.+?),/\1 /

che raggrupperà i caratteri spostandosi dall'inizio della stringa ( ^) verso la fine di un carattere ( .+?) su ogni passaggio fino a trovare il primo segno di virgola. Tutto questo gruppo insieme alla prima occorrenza di virgola verrà sostituito da group ( \1) e dallo spazio.


Nota che questo non corrisponderà a una riga che non contiene una virgola (un singolo valore su una riga). Corrispondere a qualsiasi * potrebbe essere meglio di uno +cosìs/^(.*?),/\1 /
Jeff Puckett,

Potresti anche fare s/^([^,]*),/\1 /, che corrisponderebbe all'inizio, qualsiasi cosa non una virgola, quindi una virgola. Inoltre, non sai che s//non cambia nulla che non corrisponda?
JustinCB,

1

TextPad ha sempre avuto la possibilità di utilizzare la notazione posix, ma è necessario modificare le impostazioni in una finestra di dialogo diversa. Per utilizzare le impostazioni predefinite di TextPad per le espressioni regolari, devi "sfuggire" alle parentesi di apertura e chiusura:

Sostituisci lo spazio dopo il codice postale di 5 cifre, all'inizio di ogni riga

^\([0-9]+\)[ ]

Con etichetta

\1\t

Come sopra, ^ indica l'inizio della riga

\ (è una "parentesi di escape" e segna l'inizio della prima espressione di ricerca, ovvero le cinque cifre

[0-9] + indica una o più cifre (non solo codici postali a 5 cifre)

\) è un'altra "parentesi di escape" per contrassegnare la fine della prima espressione di ricerca

[] è solo un carattere spaziale (potresti tralasciare le parentesi, ma nessuno sarebbe in grado di vederlo su questa pagina web :-)

Nell'espressione sostitutiva

\ 1 è la prima espressione di ricerca, la parte tra parentesi sopra (una o più cifre)

\ t è un carattere di tabulazione

Quindi il comando cerca e sostituisci cerca una o più cifre, seguite da uno spazio. Quindi sostituisce tutto ciò con lo stesso gruppo di cifre seguito da una scheda.

Non credo che ci sia modo di trovare semplicemente "uno spazio che arriva dopo 5 cifre" in modo da poter semplicemente sostituire lo spazio senza toccare le cifre. Devi trovare le 5 cifre (la prima stringa) seguite dallo spazio (la seconda stringa). Quindi, sebbene sembri ridondante o ingombrante, SOSTITUISCI la stringa originale di 5 cifre con ITSELF, seguita dalla scheda (la seconda stringa).

Chiunque lo sappia dimentica che i neofiti non ne hanno idea. Ecco perché lo sto spiegando per te, amico mio.

Ed Poor Math Tutor e programmatore di computer in pensione di New York City


0

Per abbinare solo la prima occorrenza di qualsiasi espressione regex, rimuovere tutti i flag. Ogni espressione regex viene fornita con i seguenti flag possibili e in genere per impostazione predefinita utilizza il flag globale che corrisponderà a più di un'occorrenza:

  • / g = Con questo flag la ricerca cerca tutte le corrispondenze, senza di essa - viene restituita solo la prima corrispondenza
  • / i = senza distinzione tra maiuscole e minuscole
  • / m = modalità multi linea
  • / s = all. per abbinare il carattere di nuova riga \ n
  • / u = unicode
  • / y = modalità adesiva (cerca in una posizione specifica)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.