Baris duplikat dimulai dengan "x", mengganti "x" dalam duplikat dengan "y"?

9

Saya punya file dengan pola berikut:

foo 111
baz
foo 222
baz
foo 333
baz

yang perlu diubah menjadi

foo 111
bar 111
baz
foo 222
bar 222
baz
foo 333
bar 333
baz

Jadi, duplikat semua baris yang dimulai dengan foo, dan ubah hanya foodalam duplikat tetapi biarkan sisa baris (yang berbeda dalam setiap kasus) utuh. Bagaimana cara melakukannya?

LB7979
sumber
Jika Anda tidak terikat pada regexp, makro akan baik-baik saja. Tidak terlalu penting dalam kasus sederhana seperti ini, tetapi jika Anda memiliki sesuatu yang sedikit lebih rumit itu adalah alternatif yang sangat valid.
PhilippFrank

Jawaban:

19

Ini dia:

:g/foo/t.|s//bar

Membusuk:

:g/foo/    " start a global command applied on all lines matching 'foo'
t.         " duplicate the current line (the cursor is now on the new line)
|          " chain a new command
s//bar     " substitute the last searched element with 'bar'

Karena gperintah akan memperbarui pola pencarian, sehingga Anda dapat menghilangkan pola untuk menggantikan dalam perintah pengganti. (ref:, :h :gcari search pattern).


Versi yang lebih lama:

:g/foo/norm! yyp:s/foo/bar^M

Membusuk:

:g            start a global command
/foo/         apply only on lines having 'foo'
norm!         execute a normal command
yyp           duplicate the line
:s//bar       replace foo with bar on the line (the duplicated one)
^M            add enter to execute the substitution

Untuk memasukkan ^Mpers Ctrl+vdan enter.

Catatan : Saya awalnya datang dengan versi "lebih lama", sebelum saya belajar tentang tperintah. Saya akan meninggalkannya tetapi saya tidak akan merekomendasikan menggunakannya. Yang pertama lebih bersih lebih mudah.

nobe4
sumber
Dipecahkan, 'versi sederhana' bekerja dengan sempurna. Versi pertama, namun, menghasilkan garis duplikat masih dimulai dengan foo....
LB7979
aneh, apakah Anda masuk ^Mseperti yang saya jelaskan?
nobe4
Buruk saya, tidak membaca dengan baik. Solusi pertama juga berfungsi!
LB7979
Saya tidak tahu mengapa Anda repot-repot termasuk versi yang rumit sama sekali. Versi yang lebih sederhana adalah ... lebih sederhana. ;) (Belum lagi menjadi POSIX compliant.) Mengapa tidak meletakkannya terlebih dahulu?
Wildcard
1
Awalnya saya datang dengan versi pertama, yang lebih alami bagi saya, karena pada saat itu saya tidak menyadarinya t, dan kemudian saya menambahkan yang kedua. Saya akan mengubah urutan, Anda benar. Bagaimana dengan yang pertama adalah POSIX?
nobe4
1

Saya melakukan hal-hal seperti ini sepanjang waktu dan hanya melakukan sesuatu seperti %s/^foo \(.*\)/foo \1\rbar \1/(sebagian karena saya juga melakukan banyak tugas serupa yang tidak dapat diubah menjadi sesuatu yang pintar menggunakan fungsi penyalinan, dan sekarang \(.*\)menjadi bagian dari memori otot saya).

Saya curiga ini bukan POSIX-compliant (tidak bekerja pada klon vi lain), tetapi menggunakan ^M( C-VReturn) alih-alih \rtampaknya berfungsi pada sebagian besar klon vi lainnya.

Random832
sumber