How to add a string to line 13 in my text file - linux

I have a very large text file that is difficult to open in text editors.
Lines 12 - 15 are:
1 15.9994
2 24.305
Atoms
I would like to add:
3 196 to line 14 and then have a blank line between 3 196 and Atoms like it is currently. I tried:
sed '14 a <3 196>' file.data
But it did not seem to change anything. Anyone know of how I can do this?

Normally, sed only writes out the changes. It does not modify the file.
If you want the input file to be modified, you can use GNU sed -i:
sed -i '14 a <3 196>' file.data
Before:
[...]
9
10
11
1 15.9994
2 24.305
Atoms
16
17
[...]
After:
[...]
9
10
11
1 15.9994
2 24.305
<3 196>
Atoms
16
17
[...]
Note: If you want it after line 13 instead of 14, change 14 to 13 in your code. Similarly, if you wanted 3 196 instead of <3 196>, change <3 196> to 3 196 in your code.

Related

Replace specific lines in one file with data contained in another file

I want to replace specific lines in one file (File 1) with data contained in another file (File 2). For example:
File 1 (Input code):
other lines...
11 !!! Regular Expression
10 0.685682*100
11 0.004910*100
12 0.007012*100
13 0.146041*100
14 0.067827*100
15 0.019460*100
16 0.019277*100
17 0.001841*100
18 0.047950*100
other lines...
File 2 (to add new data):
1 0.36600*100
2 0.44466*100
3 0.0.046*100
4 0.15544*100
5 0.16600*100
6 0.14477*100
7 0.01927*100
8 0.00188*100
9 0.05566*100
How could I replace the Input data (File 1) from line 1 to line n with the data contained in File 2 (data). I tried using sed as follows:
sed '/!!! Regular Expresion/r File2' File1
and I get the following:
1 !!! Regular Expression
2 0.36600*100
3 0.44466*100
4 0.0.046*100
5 0.15544*100
6 0.16600*100
7 0.14477*100
8 0.01927*100
9 0.00188*100
10 0.05566*100
11 0.685682*100
12 0.004910*100
13 0.007012*100
14 0.146041*100
15 0.067827*100
16 0.019460*100
17 0.019277*100
19 0.001841*100
20 0.047950*100
My problem is that this command can insert the lines contained in File 2 but not replace them. How can I replace only these lines (from 10 to 18) with the new data?.
Thanks in advance.
replace specific lines in one file from 10 to 18 with the data contained in File 2
Lets use dynamic programming and split "replacing" into "deleting" and "inserting".
[Delete] specific lines in one file from 10 to 18
That's easy:
sed '10,18d'
would delete lines from 10 to 18.
[Insert] the data contained in File 2 [to line 10]
That's also easy:
sed '9r file2'
It appends the content of file2 after line 9, so first line of file2 is the new line 10.
All together:
sed '10,18d; 9r file2'
Example:
# seq 8 | sed '3,6d; 2r '<(seq -f 2%.0f 5)
1
2
21
22
23
24
25
7
8

Shifting column titles to right

I have a file which I want to process it in bash or python.
The structure is with 4 columns but only with 3 column titles:
input.txt
1STCOLUMN 2NDCOLUMN THIRDCOLUMN
input1 12 33 45
input22 10 13 9
input4 2 23 11
input4534 3 1 1
I am trying to shift the title columns to right and add a title of "INPUTS" to the first column (input column).
Desired output: Adding the column title
Desired-output-step1.csv
INPUTS 1STCOLUMN 2NDCOLUMN THIRDCOLUMN
input1 12 33 45
input22 10 13 9
input4 2 23 11
input4534 3 1 1
I tried with sed:
sed -i '1iINPUTS, 1STCOLUMN, 2NDCOLUMN, THIRDCOLUMN' input.txt
But I do not prefer to type the names of the columns for this reason.
How do I just insert the new title to first column and the other column titles shift to right?
you can specify which line to be replaced using line numbers
$ sed '1s/^/INPUTS /' ip.txt
INPUTS 1STCOLUMN 2NDCOLUMN THIRDCOLUMN
input1 12 33 45
input22 10 13 9
input4 2 23 11
input4534 3 1 1
here, 1 indicates that you want to apply s command only for 1st line
s/^/INPUTS / insert something to start of line, you'll have to adjust the spacing as needed
instead of counting and testing the spaces, you can let column -t do the padding and formatting job:
sed '1s/^/INPUTS /' ip.txt|column -t
This will give you:
INPUTS 1STCOLUMN 2NDCOLUMN THIRDCOLUMN
input1 12 33 45
input22 10 13 9
input4 2 23 11
input4534 3 1 1

Problem getting desired output using Grep with just numbers as pattern

I am trying to grep rows from a file 2 that matches the values in file 1, but output is giving more lines.
File 1 looks like this:
$ head b.txt
5
11
26
27
File 2, a.txt, looks like
1509 5
1506 11
1507 12
339 26
1000 27
1000 100
Command I use:
grep -wFf b.txt a.txt
Results I want:
1509 5
1506 11
339 26
1000 27
It is giving me all I have in b.txt, but some extra lines too, e.g.,
1509 5
1506 11
1507 12
339 26
1000 27
1000 100
How can I fix this?
I simulated your problem and believe I know what's going on. With an empty line at the end of b.txt, I get the same output as you do. If I remove the empty line at the end of b.txt, I get your desired output.
➜ ~ grep -wFf b.txt a.txt
1509 5
1506 11
339 26
1000 27
From grep's manpage:
-f file, --file=file
Read one or more newline separated patterns from file. Empty pattern lines match every input line. Newlines are not considered part of a pattern. If file is empty, nothing
is matched.
I believe the Empty pattern lines match every input line. is the cause of your erroneous output.
Maybe you want to join files.
join -12 -21 -o1.1,1.2 <(<a.txt sort -k2) <(<b.txt sort)
will output:
1506 11
339 26
1000 27
1509 5
The command joins the second field from a.txt with the second field from b.txt. "joins" means finds specified fields in both files, where they have equal value. I "join" those two files on the second column from the first file and on the first column from the second file. join needs the inputs to be sorted by the joined fields, so we need to pipe it through sort. This method sadly will not preserve the order of the lines in files, as they need to be reordered for join to work.

Using CTRL-O in vim help files breaks with jumping to previous file

I'm using Vim 8.0, and when I browse the vim help files using CTRL-] to jump around, I find that trying to go back through the jumplist using CTRL-O works fine when the Old positions are in the current file, but things break as soon as I try to CTRL-O to an old position in a previous file. Somehow this gets treated as a jump itself, and instead of going back in the jumplist, a whole new entry is added to the jumplist instead.
The following is an example to illustrate. Suppose I was jumping around in motion.txt.gz, and then followed a link to map.txt.gz using CTRL-] and jumped around in that file. Then my jump list might look like this:
:jump
jump line col file/text
9 1 0 help.txt
8 1 0 motion.txt.gz
7 313 19 motion.txt.gz
6 75 6 motion.txt.gz
5 87 6 motion.txt.gz
4 96 64 motion.txt.gz
3 1 0 *map.txt* For Vim version 8.0. Last change: 2017 Mar 10
2 56 23 :lm[ap]^I{lhs} {rhs}^I^I|mapmode-l|^I^I*:lm* *:lmap*
1 361 12 *omap-info*
>
Great! So far so good. But now I want to use CTRL-O to navigate back through the jump list, one-by-one, say all the way back to #7 above (line 313 col 19 in motion.txt.gz). I find that CTRL-O will work fine all the way to #3 above, like so:
:jump
jump line col file/text
6 1 0 help.txt
5 1 0 motion.txt.gz
4 313 19 motion.txt.gz
3 75 6 motion.txt.gz
2 87 6 motion.txt.gz
1 96 64 motion.txt.gz
> 0 1 0 *map.txt* For Vim version 8.0. Last change: 2017 Mar 10
1 56 23 :lm[ap]^I{lhs} {rhs}^I^I|mapmode-l|^I^I*:lm* *:lmap*
2 361 7 *omap-info*
But then the next CTRL-O does something I did not expect. Instead of moving me up one more position in the jump list, vim mysteriously treats my action as a jump from the beginning of motion.txt to line 96 col 64 of motion.txt, thus adding the beginning of motion.txt to the end of the jump list (and, by rules of the vim jump list, removing its duplicate from the list):
:jump
jump line col file/text
9 1 0 help.txt
8 313 19 character |linewise|.
7 75 6 *exclusive* *inclusive*
6 87 6 *exclusive-linewise*
5 96 64 motion isn't yet), a special set of mappings can be used. See |:omap|.
4 1 0 map.txt.gz
3 56 23 map.txt.gz
2 361 7 map.txt.gz
1 1 0 *motion.txt* For Vim version 8.0. Last change: 2017 Mar 12
>
While the end result is that I am indeed at line 96 col 64 of motion.txt (not shown by the >), the problem is that my jump history is now fudged. In fact the problem repeats itself with continued use of CTRL-O from #1 above to #2 above (the top of map.txt is added and I end up at line 361 col 7 of map.txt). Basically, I am unable to navigate back to line 313 col 19 of motion.txt as I had originally wanted to.
Would really love to understand what is causing this behavior. I think I've been encountering this problem repeatedly in vim for years and just never looked into it. I hope to finally find an answer. Thanks for any help!

How can I align columns where the biggest number or greatest string is the align indicator?

How can I right align (and left align?) a block of numbers or text in vim like this:
from:
45 209 25 1
2 4 2 3
34 5 300 5
34 120 34 12
to this:
45 209 25 1
2 4 2 3
34 5 300 5
34 120 34 12
That means the biggest number or greatest string in every column doesn't move.
In the first column it is 45+34, in the second column 209+120, in the third column 300 and in the last column 12.
Have a look at the align plugin, it can do this and much more. Great tool in your utility belt!
Found here
After some serious vimhelp/reading I found the correct AlignCtrl mapping...
Visually select the table, e.g. by using ggVG, then do a \Tsp i.e. <leader>Tsp
Then I get this:
45 209 25 1
2 4 2 3
34 5 300 5
34 120 34 12
From vimhelp:
\Tsp : use Align to make a table separated by blanks |alignmap-Tsp|
(right justified)
You can look into the Tabularize plugin. So if you have something like
45 209 25 1
2 4 2 3
34 5 300 5
34 120 34 12
just select those lines in the visual mode and type :Tab/ and it will format it as
45 209 25 1
2 4 2 3
34 5 300 5
34 120 34 12
Also, it looks like you don't have an equal number of spaces separating the numbers at the moment. So before you use the plugin, replace all the multiple spaces with a single space with the following regex:
%s![^ ]\zs \+! !g
With the Align plugin you can select the rows you want to align and hit :
<Leader>Tsp
From Align.txt
\Tsp : use Align to make a table separated by blanks |alignmap-Tsp|
(right justified)
(The help mention \ because it is the default leader but in case you have changed it to something else you must adapt accordingly)
Just trying on my install, I got the following result :
45 209 25 1
2 4 2 3
34 5 300 5
34 120 34 12
In my opinion Align plugin is great but the "align maps" and various commands are not really easy to remember.
With the Align and AlignMaps plugins: select using V, then \anum (AlignMaps comes with Align). One advantage of \anum is that it also handles decimal points (commas) and scientific notation.
I think the best thing to do is to first eat all multiple spaces with
:{range}s/ \+/ /g
And then call Tabularize
:Tab / /r1
Or change that r to l.

Resources