如何在Vim中去除第一、二列周围的引号?

15

假设我有一个文本文件中包含以下格式的行:

"12" "34" "some text     "
"56" "78" "some more text"
.
.
.
etc.

我想删除前两列周围的引号。有什么最好的方法可以在 Vim 中实现吗(当前我正在使用 gVim)?

我至少想到了如何通过使用可视模式并输入命令 '<,'>s!^"!! 删除每行开头的引号。

我想知道是否有一种方法可以选择整个文本列(一个字符沿着文件直接下降...或者多于 1 个,但在这种情况下,我只需要一个)。如果可能,那么你能够对整个列应用 x 命令(删除该字符)吗?

可能有更好的方法。我正在寻找任何建议。


更新

顺便提一下,我结合了几个建议。我的 _vimrc 文件现在包含以下内容:

let @q=':%s/"\([0-9]*\)"/\1/g^M'   

注意: ^M是用CTRL+Q + Enter来模拟在运行命令后按Enter键

现在我可以通过使用宏@q来删除文件中两个数字列中的所有引号。

8个回答

28

使用可视块命令:

  • 按下Ctrl-v进入可视块模式
  • 指定一个动作,例如G(到文件结尾),或使用向上/向下箭头键
  • 针对所选块指定一个操作,例如'd'表示删除

更多信息请参阅:h visual-mode


请注意,如果在 Windows 下使用 Vim,则此方法无法运行(也许通过正确的配置可以)。 - Robert Gowland
不会,因为Windows上的Vim通常加载mswin.vim,它将Ctrl-V重新映射为粘贴。相反,应该按照:h mswin中的说明,使用Ctrl-Q进入Visual模式。 - Michael Madsen

19

使用Control-V可进行块选择,从而使您能够选择在同一字符列中的内容。

看起来您想要删除数字周围的引号。为此,请使用:

:%s/"\([0-9]*\)"/\1/g

这里有一个关于vim可用模式的列表


还有一种形式(比较丑),它会限制每行替换4次。

:%s/^\( *\)"\([ 0-9]*\)"\([ 0-9]*\)"\([ 0-9]*\)"/\1\2\3\4/g

而且,如果你手头有sed,你也可以在shell中尝试这些命令。

head -4 filename.txt | sed 's/pattern/replacement/g'

这将在文件的前4行上尝试您的命令。


我在ED4W(不同的编辑器)中能够进行块选择和删除,所以我想Vim肯定也能做类似的事情。然而,你说得对,我真正想要的是去掉数字周围的引号。这正是我一直在寻找的。谢谢! - Jason Down
这很奇怪,我正在添加一个变量让您检查。 - nik
1
我最喜欢你的第一个例子。我做了一个修改,似乎这个可以工作::%s/"([0-9]*)"/\1/g 或者可以使用 :%s/"([0-9]*)"/\1/g - Jason Down
有趣的是,一旦你解决了一个问题,真正发现这样的漏洞需要另一个人。你的思维已经将“修复”部分屏蔽了!你明确指出它不起作用,但我从来没有去看那个缺失的“。”那么你的其他列是否以数字开头?这可以解释我的错误表现。 - nik
你不需要转义引号。我给出的第一个答案(虽然有拼写错误)是正确的答案。其他答案应该只用来学习更多关于这些模式技术的知识。 - nik
显示剩余6条评论

4

如果你想删除除第一列外的所有列,可以在Vim中输入以下内容,简单易行:

:%!awk '{print $1}'

如果你想要除了第一列之外的所有列,你也可以这样做:
:%!awk '{$1="";$0=$0;$1=$1;print}'

确实需要外部工具来完成这个任务,但是awk在Linux和Mac上默认安装,而且我认为没有UNIX系统经验的人很少在Windows上使用Vim,否则你可能已经知道如何获取Windows版本的awk。


由于第二个命令的行重构副作用,您可能需要在awk代码中指定OFS变量。 - Meow
这是旧的...但当时我没有访问awk的权限(除非通过cygwin或unxutils之类的工具)。这并不意味着这不是一个有效的解决方案。 - Jason Down
我从gnuwin32测试了gawk(虽然有点老),我将二进制文件放在gvim.exe的同一目录下,它可以正常工作。 - Meow
很好。看起来这个问题有很多可行的解决方案。 - Jason Down
$0=$0是什么意思? - cokedude

3
请查看vim中的列编辑。它描述了列插入,但基本上删除操作应该以相同的方式进行。

3
虽然使用正则表达式很容易解决这个问题,但如果你要做更高级的操作,我建议像Bryan Ward一样记录一个宏。对我来说,宏比记住vim正则表达式中需要转义哪些字符更容易。而且宏很好用,因为你可以立即看到自己的更改,并且可以分段处理行变换。
在你的情况下,你会按qw开始记录一个宏在寄存器w中(当然你也可以使用任何字母)。我通常以^开头启动宏以将光标移动到行首,这样宏就不依赖于光标位置。然后你可以执行f"跳到第一个引号上,x删除它,再执行f"跳到下一个引号并再次x删除。最后按q结束录制。
不必让宏结束在下一行,我今天才发现你可以只需V(可视化行选择)选中要应用宏的所有行,然后执行:normal @w,这会将寄存器w中的宏应用于每个可视化选择的行。

我对宏并不是很熟悉,但我可以看出它们非常有用。这是我经常需要做的事情,我需要一种方便的方式来完成它,但我又不会经常这么做,所以记住正则表达式并不容易。在这种情况下,宏可能是更好的解决方案(尽管我确实应该努力掌握正则表达式...因为它们在.NET编程中也非常有用)。 - Jason Down

1
  1. Start visual-block by Ctrl+v.
  2. Jump at the end and select first two columns by pressing: G, EE.
  3. Type: :s/\%V"//g which would result in the following command:

    :'<,'>s/\%V"//g
    

    Press Enter and this will remove all " occurrences in the selected block.

请参阅:Vim Wikia上的将替代项应用于视觉块


1
你也可以创建一个宏(q)来删除引号,然后跳转到下一行。然后,通过告诉vi要执行多少次来运行它多次。所以如果你将宏保存为字母m,那么你可以运行100@m,它会删除100行的引号。有关宏的更多信息,请参阅:

http://vim.wikia.com/wiki/Macros


1

尝试了一下(我去掉了c以消除确认模式,但其他方面保持不变)。似乎只是移除了第一列周围的引号。 - Jason Down
对于前两个要求,可以使用以下命令: :%s/^"\(\d+\)"\s+"\(\d+\)"/\1 \2/如果数字之间的空格很重要,你也可以捕获它: :%s/^"\(\d+\)"\(\s+\)"\(\d+\)"/\1\2\3/ - TMN

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接