Come copiare i primi quattro caratteri di ogni riga alla fine di quella stessa riga?


10

Data una serie di linee simili a questa:

2001 "Some Kind of Title," Author's Name, Publication Name, 1 Mar.
2002 "Some Kind of Title," Author's Name, Publication Name, 12 Oct.
2003 "Some Kind of Title," Author's Name, Publication Name, 8 Apr.
2004 "Some Kind of Title," Author's Name, Publication Name, 3 Jun.

C'è un modo in cui potrei afferrare quei primi quattro personaggi (l'anno) e copiarli alla fine della riga, in modo che appaia così:

2001 "Some Kind of Title," Author's Name, Publication Name, 1 Mar. 2001
2002 "Some Kind of Title," Author's Name, Publication Name, 12 Oct. 2002
2003 "Some Kind of Title," Author's Name, Publication Name, 8 Apr. 2003
2004 "Some Kind of Title," Author's Name, Publication Name, 3 Jun. 2004

7
Certo c'è: :%g/^\d\{4}\d\@!/s/^\(\d\{4}\).*\zs/ \1/.
Sato Katsura,

Risposte:


17
:% s/\v^(\d{4})(.*)$/\1\2 \1/ 

è un modo per farlo

  • \v opzione magica, per evitare di dover sfuggire al raggruppamento ()
  • ^ inizio della linea
  • \d{4} corrisponde esattamente a quattro cifre
  • .* resto della linea
  • \1 \2 ha il modello abbinato all'interno ()

modifica: @Jair Lopez menziona nei commenti, l'espressione regolare può essere ulteriormente migliorata:

:% s/\v^(\d{4}).*/& \1/ 

o l'equivalente

:% s/\v^(\d{4}).*/\0 \1/ 
  • &e \0contiene l'intero modello abbinato

Per ulteriori letture, FAQ su vimregex e regex


3
:%s/\v^(\d{4}).*/& \1/sarebbe un comando più breve.
Jair López,

10

E una soluzione con una macro:

qqyiwA <Esc>pj0q

Che significa:

qq   Record the macro in the register q
yiw  Yank the text described by the text object iw (inner word): The date
A <Esc>   Append a white space to the end of the line and go back to insert mode
p    Paste the date
j0   Place your cursor on the first column of the next line (to be able to repeat the macro)
q    Stop recording

È quindi possibile riprodurre la macro tutte le volte che si è allineati 3@a.

Modifica Come menzionato da @evilsoup nei commenti, un modo più efficace per eseguire la macro su tutte le righe del buffer è usare:

:%normal @q

Ovviamente puoi sostituirlo %con un intervallo che descriva le linee da modificare.


3
Puoi anche eseguirlo su ogni riga con:%normal @q
evilsoup,

@evilsoup: grazie per averlo menzionato, modificherò la risposta.
statox

6

Ecco come lo farei:

:%norm y4lA <C-o>p

Spiegazione:

:%norm                     "Apply the following keystrokes to every line:
       y4l                 "Yank 4 letters. You could also do 'yiw'
          A                "Add a space to the end
            <C-o>          "Do a single normal command
                 p         "Paste

4

Se hai accesso ai comandi UNIX standard, puoi utilizzare AWK:

:%!awk '{print $0" "$1}'

Non proprio vi / vim, quindi, o i primi quattro caratteri.
pipe

1
Considerando che :help filterè una funzionalità integrata di Vim e considerando quanto bene questa funzione permetta a Vim di adattarsi al paradigma UNIX, direi che in realtà è molto vi / vim.
romainl

1

Penso che i meccanismi esistenti per farlo siano migliori, ma è anche possibile farlo usando la modalità blocco visivo .

Copia le date:

gg          # Go to the top of the file
<ctrl>y     # Enter visual block mode
G           # Go to the bottom of the file
w           # Select the first word
"jy         # Copy in to the j register

Riempi la fine della prima riga:

gg      # Top of file
A       # Append the line
        # Some spaces
<ESC>   # Return to command mode

Incolla:

gg 
# Move right to the length of the longest line
"jp   # Paste the block

Nota che puoi semplicemente fare 4linvece dillll
EvergreenTree

@EvergreenTree - Aggiornato.
sixtyfootersdude,

0

Da una riga di comando unix (o Windows se sono installati strumenti della riga di comando unix)

sed -e "s/\(....\)\(.*\)/\1\2 \1" < inputFile > outputFile
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.