Come sostituire un personaggio con una nuova riga in Vim


1967

Sto cercando di sostituire ciascuno ,nel file corrente con una nuova riga:

:%s/,/\n/g 

Ma inserisce quello che sembra un ^@anziché un vero e proprio newline. Il file non è in modalità DOS o altro.

Cosa dovrei fare?

Se sei curioso, come me, controlla la domanda Perché è \ ra newline per Vim? anche.


2
Stack Overflow è un sito per domande di programmazione e sviluppo. Questa domanda sembra fuori tema perché non si tratta di programmazione o sviluppo. Consulta quali argomenti posso chiedere qui nel Centro assistenza. Forse Super User o Unix & Linux Stack Exchange sarebbero un posto migliore da chiedere.
JWW

5
@jww questa domanda ha 10 anni ... sembra essere troppo vecchia per migrare. Ci sono un sacco di domande come questa, per esempio: stackoverflow.com/questions/10175812/...
Vinko Vrsalovic

14
@jww vim è uno strumento comunemente utilizzato per i programmatori e le domande sugli strumenti comunemente utilizzati per i programmatori sono in argomento in Stack Overflow . Anche se ovviamente questo è più adatto su Vi e Vim .
user202729,

Risposte:


2565

Usa \rinvece di \n.

Sostituendo \ninserisce un carattere null nel testo. Per ottenere una nuova riga, utilizzare \r. Durante la ricerca di una nuova riga, comunque \n, useresti comunque. Questa asimmetria è dovuta al fatto che \ne \r fa cose leggermente diverse :

\ncorrisponde a un fine riga (newline), mentre \rcorrisponde a un ritorno a capo . D'altra parte, nelle sostituzioni \ninserisce un carattere null mentre \rinserisce una nuova riga (più precisamente, viene trattata come input <CR>). Ecco un piccolo esempio non interattivo per illustrare questo, utilizzando la funzione della riga di comando di Vim (in altre parole, è possibile copiare e incollare quanto segue in un terminale per eseguirlo). xxdmostra un dump esadecimale del file risultante.

echo bar > test
(echo 'Before:'; xxd test) > output.txt
vim test '+s/b/\n/' '+s/a/\r/' +wq
(echo 'After:'; xxd test) >> output.txt
more output.txt
Before:
0000000: 6261 720a                                bar.
After:
0000000: 000a 720a                                ..r.

In altre parole, \nha inserito il byte 0x00 nel testo; \rha inserito il byte 0x0a.


127
/ r viene considerato come premere il tasto Invio / Invio. Funziona su tutte le piattaforme.
Luka Marinko,


14
Vorrei che funzionasse per il classico vi. Su AIX v6.1, \rnon funziona in questo modo. Ma puoi premere Ctrl-V Enteral posto della digitazione \r, e funziona.
eksortso,

3
Sono in ritardo alla festa. Se \rinserisce <CR>e \ninserisce un valore null, come sostituirei qualcosa con un ritorno a capo?
Mr. Llama,

2
@SunnyRaj sei sicuro della storia di CR e LF? Avevo l'impressione che originariamente LF avesse spostato la carta di una riga in avanti ma non avesse spostato la testina di stampa e che CR avesse spostato la testina di stampa ma non avesse spostato la carta. Di conseguenza, se il sistema operativo in uso non ha convertito l'input prima della stampa, non è possibile utilizzare solo LF o CR per ottenere l'output corretto. MS DOS utilizzava i dati di stampa grezzi come formato di file di testo, Mac OS utilizzava CR e li convertiva nel formato non elaborato della stampante e UNIX utilizzava LF e li convertiva nel formato non elaborato della stampante.
Mikko Rantalainen il

210

Ecco il trucco:

Innanzitutto, imposta la sessione Vi (m) in modo da consentire la corrispondenza del modello con caratteri speciali (ad esempio: newline). Probabilmente vale la pena mettere questa riga nel tuo file .vimrc o .exrc:

:set magic

Quindi, fai:

:s/,/,^M/g

Per ottenere il ^Mpersonaggio, digita Ctrl+ Ve premi Enter. In Windows, fare Ctrl+ Q, Enter. L'unico modo in cui posso ricordare questi è ricordando quanto poco senso abbiano:

A: Quale sarebbe il peggior personaggio di controllo da usare per rappresentare una nuova linea?

B: O q(perché di solito significa "Esci") o vperché sarebbe così facile digitare Ctrl+ Cper errore e uccidere l'editor.

A: Rendilo così.


9
Sto usando GVim su Windows e non ho bisogno né del :set magic(non è nemmeno nel mio ~ / _vimrc) o ctrl-q. Solo un semplice ctrl-vseguito da invio crea il ^Mpersonaggio per me bene.
Chris Phillips,

5
Cv non rappresenta una newline; è il comando "evita il prossimo personaggio letterale". Non so che Cv sia un mnemonico per entrambi, ma c'è una ragione per cui non mappa mentalmente a newline.
Jim Stewart,

27
Ctrl-v è un mnemonico per "verbatim" - cioè scappa dal prossimo tasto premuto al suo codice / carattere "verbatim". In Windows è incolla: per mantenere le cose familiari. Ctrl-Q è forse per "(un) Quote". Abbastanza stupido, comunque - ma puoi usarlo in file binari - ad esempio per cercare da Ctrl-A a Ctrl-Z (Ascii 1-26 immagino).
Tomasz Gandor,

1
Ctrl-Cin realtà non uccide l'editor, anche se può tornare alla modalità normale. Ctrl-Vsignifica letteralmente e Ctrl-Qsignifica che qualcuno ha commesso l'errore di caricare il $VIMRUNTIME/mswin.vimfile di configurazione. Non hai bisogno di mswin. Usa invece il tuo vimrc.
00dani,

wow ---- questo è fantastico. Lo facevo sed -n l fino ad ora. Buono a sapersi che lo stesso può essere realizzato con Ctrl-vin vim.
arpit

98

Nella sintassi s/foo/bar, \re \nhanno significati diversi, a seconda del contesto.


Corto:

Per foo:

\ n = newline (LF su Linux / Mac, CR + LF su Windows)
\ r = ritorno a capo (CR)

Per bar:

\ r = is newline
\ n = null byte.

Più a lungo (con numeri ASCII):

NUL= 0x00 = 0 = Ctrl+ @
LF= 0x0A = 10 = Ctrl+ J
CR= 0x0D = 13 = Ctrl+M

Ecco un elenco dei caratteri di controllo ASCII . Inseriscili in Vim tramite Ctrl+ V, Ctrl+ ---key---.

In Bash o nelle altre shell Unix / Linux, basta digitare Ctrl+ ---key---.

Prova Ctrl+ Min Bash. È come colpire Enter, poiché la shell capisce cosa si intende, anche se i sistemi Linux usano feed di linea per la delimitazione di linee.

Per inserire valori letterali in bash, anche farli precedere con Ctrl+ Vfunzionerà.

Prova in Bash:

echo ^[[33;1mcolored.^[[0mnot colored.

Questo utilizza sequenze di escape ANSI . Inserire le due ^['s via Ctrl+ V, Esc.

Si potrebbe anche provare Ctrl+ V, Ctrl+ M, Enter, che vi darà questa:

bash: $'\r': command not found

Ricordi \rdall'alto? :>

Questo elenco di caratteri di controllo ASCII è diverso da una tabella di simboli ASCII completa , in quanto i caratteri di controllo, che sono inseriti in una console / pseudoterminal / Vim tramite la Ctrlchiave (haha), possono essere trovati lì.

Mentre in C e nella maggior parte delle altre lingue, di solito usi i codici ottali per rappresentare questi "caratteri".

Se vuoi davvero sapere da dove viene tutto questo: il TTY si è demistificato . Questo è il miglior collegamento che troverai su questo argomento, ma attenzione: ci sono draghi.


TL; DR

Di solito foo= \ne bar= \r.


1
Quindi sono incuriosito da come sostituiresti un personaggio con un ritorno a
capo

2
@codeshot :s/x/^M/gdovrebbe fare. Inserire la ^Mvia ctrl-vseguita da ctrl-m.
sjas,

3
Grazie, sai, questa domanda è una delle più strane di tutti i tempi. 1008 voti per la risposta che sostanzialmente non dice altro che "vim fa quello che hai trovato. Questo perché vim fa quello che hai trovato. Non dimenticare mai che vim fa quello che hai trovato." Speravo di trovare un elenco di codici per personaggi interessanti nel modello, la sostituzione e il motivo della stranezza, quindi è facile da ricordare e prevedere altre stranezze simili. Ciò avrebbe ottenuto il mio voto.
codeshot

@codeshot potrebbe aiutarti un elenco di caratteri di controllo ASCII. Vedere cs.tut.fi/~jkorpela/chars/c0.html per ulteriori riferimenti. Aggiornerò la mia risposta per includere due collegamenti.
sjas,

55

Devi usare:

:%s/,/^M/g

Per ottenere il ^Mpersonaggio, premi Ctrl+ vseguito da Enter.


4
Devo fare <Cv> <Cm> per ottenere il carattere ^ M.
Jezen Thomas,


24

Con Vim su Windows, usa Ctrl+ Qal posto di Ctrl+ V.


16

Questa è la risposta migliore per il modo in cui penso, ma sarebbe stato più bello in una tabella:

Perché \ ra newline per Vim?

Quindi, riformulazione:

È necessario utilizzare \rper utilizzare un avanzamento riga (ASCII 0x0A, la nuova riga Unix) in una sostituzione regex, ma questo è peculiare per la sostituzione - normalmente si dovrebbe continuare ad aspettarsi di utilizzare \nper l'avanzamento riga e \rper il ritorno a capo.

Questo perché Vim ha usato \nun sostituto per indicare il carattere NIL (ASCII 0x00). Probabilmente ti aspettavi che NIL fosse stato \0invece, libero \nper il suo uso normale per l'alimentazione di riga, ma \0ha già un significato nelle sostituzioni regex, quindi è stato spostato su \n. Quindi, andando oltre, sposta anche la newline da \na \r(che in un modello regex è il carattere di ritorno a capo, ASCII 0x0D).

Carattere | Codice ASCII | Rappresentazione C | Partita Regex | Sostituzione Regex
------------------------- + ------------ + ----------- ------- + ------------- + ------------------------
zero | 0x00 | \ 0 | \ 0 | \ n
avanzamento riga (Unix newline) | 0x0a | \ n | \ n | \ r
ritorno a capo | 0x0d | | | <Sconosciuto>

NB: ^M( Ctrl+ V Ctrl+ Msu Linux) inserisce una nuova riga quando viene utilizzato in una sostituzione regex anziché in un ritorno a capo come altri hanno consigliato (l'ho appena provato).

Si noti inoltre che Vim tradurrà il carattere di avanzamento riga quando salva in un file in base alle impostazioni del formato del file e ciò potrebbe confondere le cose.


11

Da Eclipse , i ^Mpersonaggi possono essere incorporati in una linea e si desidera convertirli in nuove righe.

:s/\r/\r/g

8

Ma se uno deve sostituire, allora la seguente cosa funziona:

:%s/\n/\r\|\-\r/g

In quanto sopra, ogni riga successiva viene sostituita con la riga successiva e quindi di |-nuovo una nuova riga. Questo è usato nelle tabelle wiki.

Se il testo è il seguente:

line1
line2
line3

È stato modificato in

line1
|-
line2
|-
line3

7

Se è necessario farlo per un intero file, mi è stato anche suggerito di provare dalla riga di comando:

sed 's/\\n/\n/g' file > newfile

1
Nota che ciò richiede GNU sed. Prova printf 'foo\\nbar\n' | sed 's/\\n/\n/g'a vedere se funzionerà sul tuo sistema. (Ringraziamo la brava gente di #bash su freenode per questo suggerimento.)
Evan Donovan,

Sì, ma la domanda riguardava Vim. C'è una domanda di overflow dello stack Come posso sostituire una newline (\ n) usando sed? .
Peter Mortensen,

5

Ecco la risposta che ha funzionato per me. Da questo ragazzo:

---- quoting Utilizzare l'editor vi per inserire un carattere di nuova riga in sostituzione


Qualcos'altro che devo fare e che non riesco a ricordare e poi devo cercare.

In vi, per inserire un carattere di nuova riga in una ricerca e sostituirlo, procedi come segue:

:%s/look_for/replace_with^M/g

Il comando sopra sostituirà tutte le istanze di “look_for” con “sostituisci_con \ n” (con \ n che significa newline).

Per ottenere la “^ M”, inserire la combinazione di tasti Ctrl+ V, quindi premere (rilasciare tutti i tasti) Enter.


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.