I'm totally new to vim and I know what magical things vim can do. My requirement is to append a sequence of numbers at the end of each line and I saw somebody did that before in front of me. It's just that I don't have enough time to search for the correct command, so I think post a question here should be a faster way since I'm running out of time. Sorry for being a noob but seems this is the only way I can come up with.
So the sample file content is like
1 Afghanistan
2 Albania
3 Algeria
4 American
5 Andorra
6 Angola
7 Anguilla
8 Antarctica
a list of countries, imagine it is a database table and each column is separated with tab. I already figured out a way to append tab to the end of each line, but now the problem is to add a number at the end of each line as well, and the number for each line is exactly same with its id(the first number)
I somehow think that it should be done with visual mode, but please tell me a working solution if you know. Any help is highly appreciated.
Best Regards,
Hai Lang
Open your file in vim. Press ESC if not in escape mode.
write this :%s/$/\=line('.')/
This will append the sequence of numbers at the end of each line. To add numbers in the begining do
:%s/^/\=line('.')/
Input:
1 Afghanistan
2 Albania
3 Algeria
4 American
5 Andorra
6 Angola
7 Anguilla
8 Antarctica
Keystrokes:
:%s!^\(\d\+\).*!&\t\1<CR>
Output:
1 Afghanistan 1
2 Albania 2
3 Algeria 3
4 American 4
5 Andorra 5
6 Angola 6
7 Anguilla 7
8 Antarctica 8
Par : 20
Explanation:
: : start the command
% : on all lines
s : subsititute
! : start of pattern
^ : start of line
\( : start of group
\d : digit
\+ : one or more
\) : end of group
. : any character
* : any number of those
! : end of pattern
& : replace with - whole pattern
\t : a tab
\1 : first matched group
Carriage-return : execute
You could use recordings, which are enabled by q followed by a letter, which is the bookmark for that recording.
E.g.
In normal mode go to the first line and type:
qe
^
y<space>
$
p
q (to end the recording)
Now type #e to play the recording from letter e or 20#e, which repeats #e 20 times.
You can play around with the recordings like this. Maybe also record a j, in normal mode so it takes you to the next line.
Related
Specifically, I know ahead of time I only need to swap position 1 and 2 with 4 and 5.
2 Examples:
HEART
New output:
RTAHE
12734
New output:
34712
There is probably more than a handful of ways to do this. If you're interested in a formula, here is one way to go about it:
=RIGHT(A3,2)&MID(A3,3,LEN(A3)-4)&LEFT(A3,2)
Seems to be working on some test data I threw together.
A bit more robust, as suggested by #Rafalon:
=MID(A3,4,2)&MID(A3,3,1)&LEFT(A3,2)&MID(A3,6,LEN(A3))
Produces following results:
Input
1
12
123
1234
12345
123456
1234567
Output
1
12
312
4312
45312
453126
4531267
I want to be able to print a long list into 1 block in a column (Column G line 8 for example):
The given list:
1 bag of fish 2 bag of fish 3 bag of fish 4 bag of fish 5 bag of fish
In my excel block it will look as printed above in 1 long horizontal line (but it will be considered in Column G line 8).
How do I alter that block so that it can look like this:
1 bag of fish
2 bag of fish
3 bag of fish
4 bag of fish
5 bag of fish
but without extending to line 6, 7, 8 etc..
Any advise would be greatly appreciated!
I have figured out a solution! In the 'Home' selection on Microsoft Excel there is a widget called 'Wrap Text'.
Highlight the block you want 'wrapped' and it will do just that! Hope this helps others!
Input data:
name Age Zodiac Grade City pahun
0 /extract 30 Aries A Aura a_b_c
1 /abc/236466/touchbar.html 20 Leo AB Somerville c_d_e
2 Brenda4 25 Virgo B Hendersonville f_g
3 /abc/256476/mouse.html 18 Libra AA Gannon h_i_j
I am trying to extract the rows based on the regex on the name column. This regex extracts the numbers which has 6 as length.
For example:
/abc/236466/touchbar.html - 236466
Here is the code I have used
df=df[df['name'].str.match(r'\d{6}') == True]
The above line is not matching at all.
Expected:
name Age Zodiac Grade City pahun
0 /abc/236466/touchbar.html 20 Leo AB Somerville c_d_e
1 /abc/256476/mouse.html 18 Libra AA Gannon h_i_j
Can anyone tell me where am I doing wrong?
str.match only searches for a match at the start of the string.
Use str.contains with a regex like
df=df[df['name'].str.contains(r'/\d{6}/')]
to find entries containing / + 6 digits + /.
Or, to make sure you just match 6 digit chunks and not 7+ digit chunks:
df=df[df['name'].str.contains(r'(?<!\d)\d{6}(?!\d)')]
where
(?<!\d) - makes sure there is no digit on the left
\d{6} - any six digits
(?!\d) - no digit on the right is allowed.
You are almost there, use str.contains instead:
df[df['name'].str.contains(r'\d{6,}')]
I am manipulating some string variables and certain cells are returning unexpected values with substring and length functions. These cells hold character-formatted dates, as I need to do a few manipulations before converting them to SAS dates, because of the nature of the Excel file they're coming from. Here is an example:
HAVE:
Obs _orig
1 4/3
2 12/16
3 1/13
4 6/2
5 3/10
6 5/4
7 10/14
WANT:
Obs _orig _length _sub_1_2
1 4/3 3 4/
2 12/16 5 12
3 1/13 4 1/
4 6/2 3 6/
5 3/10 4 3/
6 5/4 3 5/
7 10/14 5 10
I am using this code:
data want;
set have;
_strip=strip(_orig);
_sub_1_2=substr(_strip,1,2);
_length=length(_strip);
run;
This is what I get. The discrepancies are bolded.
Obs _orig _length _sub_1_2
1 4/3 5
2 12/16 5 12
3 1/13 4 1/
4 6/2 3 6/
5 3/10 4 3/
6 5/4 5
7 10/14 5 10
Both are cases where SAS calculates length=5 when length should = 3. In both cases, the value for the substring-derived variable is blank altogether. Results are the same if I use compress(), trim(), or trimn() in my code, rather than strip(). Thank you for any help you can provide
Sounds like maybe unprintable characters got in your data. If you PUT _orig $hex.; to the log, what do you see? Should be: 342F332020
152 data want;
153 length orig $5;
154 orig='4/3';
155 len=length(orig);
156 put orig= len=;
157 put orig hex.;
158 run;
orig=4/3 len=3
342F332020
To get rid of non-printable characters, you could try:
_strip=compress(orig,,'kw');
Seems pretty clear to me that your variables have leading spaces or other leading characters that look like spaces on the screen. So for OBS=6 the value of the string is more like " 5/4" which has a length of 5 and the first two characters both look like spaces. If LENGTHN() of your new _sub_1_2 variable is not 0 then it has some non-printing character there. Perhaps something like 'A0'X which some webpages use as a non-breaking space or tab character ('09'x).
I suspect that you don't want the first two characters, but instead want the first word when using / as the delimiter. You can use the LEFT() or STRIP() function to remove the leading blanks. Or COMPRESS() to remove other junk. So you might use COMPRESS() with the k and d modifiers to only keep the digits and slashes.
data want;
set have;
length first $5 ;
first = scan(compress(_orig,'/','kd'),1,'/');
run;
I have a dataset like by inserting a new column of data between 1st column
M1 M2 M3 M4
G1 1 2 3 4
G2 4 3 2 1
...
G120 1 3 4 2
I would like to modify dataset with another column of data in vim to
M1 M2 M3 M4
G1 1 1 2 3 4
G2 1 4 3 2 1
...
G120 1 1 3 4 2
i assume you use \t to align your text. then regex can be used
:%s/^\(G\d\+\)/\1\t1/
Vim's blockwise visual mode, ctrl-v, is probably the best way to do this.
In particular, you should use "Visual-block Insert" (vim help: :help v_b_I)
With your example, with the cursor at |1| in normal mode:
M1 M2 M3 M4
G1 |1| 2 3 4
G2 4 3 2 1
...
G120 1 3 4 2
Do the following:
ctrl-v - start visual blockwise selection
3j - extend selection 3 lines down (can substitute any other movement command here)
I - begin block insert mode
1<space><space><space><space><space> - the text you want inserted every line
Esc or ctrl-[ (its synonym) - complete the visual-block insert
Visual block insert can also be used to indent/unindent multiple lines, append text to every line (even if they don't end on the same column), etc, etc.