I want to convert the vertical text in my file to horizontal. like
1
2
3
to
1 2 3
I can do this using the tr command tr '\n' ' ' <file
but I want to do this using vim
An easy one. Use a range from first line until last one and join them with an space between them:
:0,$join
Select the lines and join them with J.
From :h J :
*J*
J Join [count] lines, with a minimum of two lines.
Remove the indent and insert up to two spaces (see
below).
*v_J*
{Visual}J Join the highlighted lines, with a minimum of two
lines. Remove the indent and insert up to two spaces
(see below). {not in Vi}
And, just for the fun of it:
:{fromLine},{toLine}!tr '\n' ' '
Another way:
By replacing \n with
:{fromLine},{toLine}s/\n/ /g
Related
Suppose I have something like this:
line 1 with text
line 2 with text
line 3 with text
line 4 with text
I want to unindent all of these lines to the beginning, like this:
line 1 with text
line 2 with text
line 3 with text
line 4 with text
Shift + V < gives me ONE level of un-indentation. How can I get them all to the beginning? Sorry, I'm having trouble phrasing this...
There are two different ways you could do this:
Visually select all of the lines, press <, and then press . as many times as you need until there is no indent left. Or if there are a specific number of lines you would like this on, you could do something like
5<< (unindent 5 lines)
<j (unindent this line and the next)
<ip (unindent inside this paragraph)
followed by as many . as you need.
Select all of the lines, and then type either :norm d^ or :s/^\s*
Also, Shift-V + V + < is basically the same as <<.
In vim, in a Windows machine (with no access to "unix"-like commands such command column) I want to reformat this code to make it more readable:
COLUMN KEY_ID FORMAT 9999999999
COLUMN VALUE_1 FORMAT 99
COLUMN VALUE_2 FORMAT 99
COLUMN VALUE_3 FORMAT 999
COLUMN VALUE_4 FORMAT 999
And I want to have this using as less commands as possible:
COLUMN KEY_ID FORMAT 9999999999
COLUMN VALUE_1 FORMAT 99
COLUMN VALUE_2 FORMAT 99
COLUMN VALUE_3 FORMAT 999
COLUMN VALUE_4 FORMAT 999
Note this is just an excerpt, as there many more lines in which I must do the same.
You could use the following command:
:%s/\w\zs\s*\zeFORMAT/^I
The pattern will match the whitespaces between FORMAT and the end of the previous word and replace it by a tab:
\w Any 'word' character
\zs Start the matching
\s* Any number of whitespace
\ze End the matching
FORMAT The actual word format
\zs and \ze allow to apply the substitution only on the whitespaces see: :h /\zs and :h /\ze
Note that ^I should be inserted with ctrl+vtab
The tabular plugin recommended by #SatoKatsura would be a good way to do it too.
You can also generalize that. Let's say you have the following file:
COLUMN KEY_ID FORMAT 9999999999
COLUMN VALUE_1 FOO 99
COLUMN VALUE_2 BAR 99
You could use this command:
:%s/^\(\w*\s\)\{1}\w*\zs\s*\ze/
Were the pattern can be detailed like that:
^ Match the beginning of the line
\(\w*\s\)\{1} One occurrence of the pattern \w*\s i.e. one column
\w* Another column
\zs\s*\ze The whitespaces after the previous column
You could change the value of \{1} to apply the command on the next columns.
EDIT to answer #aturegano comment, here is a way to align the column to another one:
%s/^\(\w*\s\)\{1}\w*\zs\s*\ze/\=repeat(' ', 30-matchstrpos(getline('.'), submatch(0))[1])
The idea is still to match the whitespaces which must be aligned, on the second part of the substitution command we use a sub-replace-expression (See :h sub-replace-expression).
This allows us to use a command from the substitution part, which can be explained like this:
\= Interpret the next characters as a command
repeat(' ', XX) Replace the match with XX whitespaces
XX is decomposed like this:
30- 30 less the next expression
matchstrpos()[1] Returns the columns where the second argument appears in the first one
getline('.') The current line (i.e. the one containing the match
submatch(0) The matched string
[1] Necessary since matchstrpos() returns a list:
[matchedString, StartPosition, EndPosition]
and we are looking for the second value.
You then simply have to replace 30 by the column where you want to move your next column.
See :h matchstrpos(), :h getline() and :h submatch()
For alignment, there are three well-known plugins:
the venerable Align - Help folks to align text, eqns, declarations, tables, etc
the modern tabular
the contender vim-easy-align
Posting an answer as requested:
:g/^COLUMN / s/.*/\=call('printf', ['%s %-30s %s %s'] + split(submatch(0)))/
Explanation:
g/^COLUMN / - apply the following command to lines matching /^COLUMN / (cf. :h :global)
\= - replace with the result of evaluating an expression, rather than with a fixed string (cf. :h s/\=)
submatch(0) - the line being matched
split(...) - split line into words
printf(...) - format the line
call(...) - we'd like to have printf('%s %-30s %s %s', list), but printf() doesn't take "real" lists as arguments, so we have to unfold the list with a call(...) (cf. :h call()).
Yet another solution:
:%s/ \{2,}/ /g
This solution is not perfect because the result will have an extra single space on the first line. To fix this problem:
:%s/\%>15c \{2,}/ /g
Explanation of pattern:
%>15c\s\{2,}
%>15c Matches only after column 15
\s\{2,} Matches two or more white spaces
How to change/yank the string between two blank spaces? I have tried ci[hit space bar] but it doesn't work..
Use ciW (change inner WORD)
From :h WORD :
A WORD consists of a sequence of non-blank characters, separated with white
space. An empty line is also considered to be a WORD.
It is w for word, not , i.e. change inner word ciw or yank inner word yiw, respectively.
Update for the given example, let | denote the carret
id="remember_me" name="_r|emember_me" value="on"
Hit ciW
id="remember_me" | value="on"
I need to remove the unique lines and keep the duplicates in my text file(read the articles written to remove duplicate lines but I want to do the opposite). Is there any way I could do that using expressions or textfx?
E.g:
file1.txt
hello
world
hello
After operation, output should be
hello
hello
Thanks in advance
In the Replace dialogue:
Find:
^(.+)\r?\n(?!(.|\r?\n)*\1)
Replace:
*leave empty!*
Options:
Select radio button "Regular Expression"
Leave checkbox ". matches newline" unselected
Pros:
Duplicate line doesn't need to be immediately after the 1st occurrence
Cons:
If a line appears x times in your data, after the regex x-1 occurrences will be left and not x as asked in OP.
This finds all lines followed by a line repetition (it does NOT find the last line, though):
.+\r\n(?=(.+\r\n)\1)
000000 111111 22
This matches a non-empty line 0, but only if it is followed by (a non-empty line \1, which is followed by \1).
Note that this assumes \r\n (Windows) line separations. On a Unix text file, just \n, on a Mac text file, just \r.
In the search box, mark Regular expression, unmark . matches newline, Replace with = "".
Example:
"Zulu
Alpha
Alpha
Bravo
Charlie
Charlie
Delta
Echo
Echo
Foxtrott
"
(file ends with empty line)
-->
"Alpha
Alpha
Charlie
Charlie
Echo
Echo
Foxtrott
"
I'm working with a large text file and need to be able delete lines based on the value of the 25th character on the line, i.e. if it is equal to H, K or Z. Is this possible, either just by matching one of the letters and running 3 commands or (even better) by all 3 in one command? Any help greatly appreciated!
You can use global to find a regex and then execute a command on the line that regex was found.
In this case it looks for any character 24 times from the beginning of the line and if the character after it matches H, K, or Z delete that line. (d at the end of the command stands for delete).
:g/^.\{24\}[HKZ]/d
Edit: as Peter Ricker points out \%25c would also work.
:g/\%25c[HKZ]/d
\%25c matches the 25th column then preforms the regex from there.
You could also use \%v if you wanted to match virtual columns instead.
You can try following ex command:
:if match( "HKZ", strpart( getline("."), 24, 1) ) != -1 | delete | endif