0

How can I write out the nth word of all lines to a new file? For example, I want the second word of all lines wrote out in new_file.txt:

old_file.txt:

pippo pluto paperino gigi lui marco piero andrea chiara 

new_file.txt:

pluto lui andrea 
5
  • 1
    is shelling out to awk acceptable? Does it have to be from within vi/vim? Commented Jul 11, 2019 at 14:58
  • How are fields seperated? Is it a space or a tab? Commented Jul 11, 2019 at 15:19
  • If these are names, could someone have a nickname, such as Jeff "data checker" Schaller, where the 2nd field contains a quoted delimiter? Commented Jul 11, 2019 at 15:20
  • 1
    I 'd like do this without awk. Words are separated by space. The word could be any thinks, not only name (as the ex.) Commented Jul 12, 2019 at 8:17
  • You might want to check out the Vi and Vim Stack Exchange for questions on Vim! Commented Jul 18, 2019 at 12:29

4 Answers 4

2

First step, delete all but the second word on each line. This is a fairly straightforward :%norm command:

:%norm dwwhD 

Which is like manually typing out dwwhD on each line, but faster. Second step, save to a new file:

:w new_file.txt 

And then quit without saving so that old_file.txt stays unmodified:

:q! 
2
  • Thanks a lot, but in my file a word is composed with '/' : "pippo/dui", the command dwwhD recognize pippo as single word (i.e. '/' is a word separator). Can I change word separator? Commented Jul 12, 2019 at 8:20
  • solved: added the backslash ascii to the variable iskeyword in file .vimrc. Thank you! Commented Jul 12, 2019 at 8:59
2
:!cut % '-d ' -f2 > new_file.txt 

Note that the default delimiter of cut is tab, so you'll want to use '-d ' to set the delimiter to space.

From inside of Vi you can use % as the replacement for the current filename.

0

You can do this from the terminal command line using a simple bash script. First loop through the contents of the file. Then for each line, pipe an echo into awk and have awk extract the second column. Lastly redirect that text into a new file.

Putting all of that together:

while read line; do echo $line | awk '{print $2}' >> new_file.txt done <old_file.txt 
1
  • 3
    awk '{print $2}' old_file.txt > new_file.txt will work just as well, with no loop. Commented Jul 11, 2019 at 16:36
0

Use a :s command with a regular expression:

:%s/\v^\s*\S+(\s+(\S+).*)?/\2 

The \v tells Vim to use the "very magic" style of regexps, which is similar to extended regexps in grep, or pcre.

The regexp matches a single word at the start, possibly preceded by some optional whitespace. Then, after some more whitespace, the second word is captured inside group \2. Finally, a .* matches the whole rest of the line.

The part after the first word is optional (grouped in parentheses and made optional with the final ?). This ensures lines with a single word will still be matched, and in this case they'll be replaced with a blank line, which I imagine is what should be expected of a line with a single word, since the second work is blank in that case. This is one advantage of using regexps for this task, as you get more control over what to do with lines that have corner cases.

Finally, group \2 is used for replacement. It captured the second word on the line, by itself.

You can then save the modified contents to the new filename:

:saveas new_file.txt 

This will preserve your unmodified old_file.txt and will make sure further modifications of the current buffer will only go to new_file.txt.

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.