Run a command for multiple lines in VIM

A frequently used VIM function for me is filtering a file (or selecting text) with an external command and replacing the selection with the result, for example:

:'<,>'!sort 

So

 c b a 

will sort and result in

 a b c 

You can also replace the current line with the return value of an external command, for example:

 :,!ls | wc -l 

will insert the number of files in the current directory (in my case, for example :)

 41 

But is there a way to pass a string to a shell command? For example, this could be the content of my visual selection:

 line_x line_y line_z 

I need to execute some shell command and take each of the selected lines as one shell script parameter, for example:

 my_bash_command line_x -c -e -f my_bash_command line_y -c -e -f my_bash_command line_z -c -e -f 

What is the best way to do this?

+6
source share
3 answers

I suggest you use xargs -L1

Example:

 :%!xargs -L1 wc -l 

Basically, xargs [cmd] will start the next [cmd] with several parameters from several lines. But with the argument -L1 [cmd] command will be executed for each line.

If you need to provide a specific order of arguments for your command, you can use the xargs -I option to provide a template that will be replaced by a list of arguments.

Example:

 :%!xargs -L1 -I {} rake {} --trace 

If you feel very adventurous, you can simply execute the code directly like this:

 :%!bash 
+9
source
 echo map(getline("'<", "'>"), 'system(v:val)[:-2]') :h map() :h system() " [:-2] ~> chomp 

You can use the line insert function instead of :echo if you want ( :put , setline() , etc.).

+2
source

A macro is probably the easiest way. Place the cursor at the beginning of the first line and record by making it one. Then you can run the macro over many lines. For example, this will pass arg for the echo and replace the results in the string with an argument. Enter them with the cursor somewhere in the first line of commands.

 qa0y$:r!echo <Cr>"<Enter>kddjq 

This line wrote the macro to register a (qa), moved to the beginning of line (0), copied the entire line (y $), switched to command line mode (:), read the result of the command to the line below your (r! Echo .. ..), Cr followed by "inserts your text into the command: r, k moved you back to the original line, dd deleted the line, j moved you to the next line (should contain the next command), and then stop writing (q) .

Now you can run the macro on each line either by pressing @a (after that, as soon as @@ repeats the last run macro) or by clicking on the number of times you want to run the 5 @a macro. Or better yet, select the lines and press: norm! @a

It seems like when you enter text, but when you get used to macros, they save real time savings. You basically do what you want on the first line, and then again vim replay your strokes. To solve this problem, a little practice is required, like a set of repeated tasks, but this is not what we are doing anyway :)

+1
source

Source: https://habr.com/ru/post/893162/


All Articles