Using sed to remove string between two other stings in specific column - sed

I want sed to look at only the first column of a tab-delimited file and remove everything between some string and the first tab for all rows. Sorry if this is repetitive, have searched other entries and cannot seem to find anything quite right.
For example, input:
blah-a_blah-b.13_blah-x_blah-y 0 0 0 0 0 17.983559
desired output:
blah-a_blah-b.13 0 0 0 0 0 17.983559
Tried unsuccessfully various iterations of below:
sed -i 's/\(\.[0-9]\).*\([^\t]\)//1' file
Advice?

This should work in gnu-sed:
sed -E 's/^([^\t]*\.[0-9]+)[^\t]+/\1/' file
blah-a_blah-b.13 0 0 0 0 0 17.983559
For non-gnu sed use:
sed -E 's/^([^[:blank:]]*\.[0-9]+)[^[:blank:]]+/\1/' file

Related

How to update a specific key in a specific section using sed?

I have an ini file similar to the following one:
[seciton1]
key1 = 0
key2 = 0
[section2]
key1 = 0
key2 = 0
I want to update key1 of section "section2" from 0 to 1. what will be the accurate sed command for the same.
also is sed command supported in SSH.NET c# library? if not then what are the ways using ssh.net we can update ini file.
This will update key2 once when its after section2:
awk '/section2/ {f=1} /key2/ && f {$3=1;f=0} 1' file
[seciton1]
key1 = 0
key2 = 0
[section2]
key1 = 0
key2 = 1
To write it back to the original file, do:
awk '/section2/ {f=1} /key2/ && f {$3=1;f=0} 1' file > tmp && mv tmp file
This might work for you (GNU sed):
sed -i '/^\[/h;G;/section2/s/\(key1 = \).*/\11/m;P;d' file
Make a copy of the section header and append it to each line. If the current section header is section2 substitute 1 for the value of key1.
N.B. The m flag in the substitute command restricts the .* to the remainder of the first line (of the now two lines in the pattern space i.e. the current line and the appended section header) only.

sed: behavior of H and D

My sed script is this:
# script.sed
1,3H
1,3g
3D
When I run it, I get the following:
$ seq 5 | sed -f script.sed
1
1
2
4
5
However, this seems wrong to me. On line 3, once the D command is executed, the pattern space has
1
2
3
When the cycle is restarted, H should set the hold space to:
<empty_line>
1
2
3
1
2
3
Then, g should set the pattern space to the same content. D will then remove the first (empty) line. Every time the cycle is restarted, the hold space will effectively double. Hence, this should lead to an infinite loop.
What am I missing?
Below, I show how I interpret the expected execution, showing as an ordered pair the result of the command, with the pattern space first and the hold space following:
1: H(1,\n1) g(\n1,\n1) > \n1\n
2: H(2,\n1\n2) g(\n1\n2,\n1\n2) > \n1\n2\n
3: H(3,\n1\n2\n3) g(\n1\n2\n3,\n1\n2\n3) D(,\n1\n2\n3) >
4: > 4\n
5: > 5\n
If I take the output of this interpretation and concatenate it into an echo command with the -e option, I get:
$ echo -e '\n1\n\n1\n2\n4\n5\n'
1
1
2
4
5

sed: Delete first line of hold space?

How do I delete the first line of the hold space in sed?
I've tried
x;
s/.*\n//;
x;
But .*\n matches up to the last newline, deleting all the lines except for the last one.
this should remove the 1st line from "hold space"
x;s/[^\n]*\n//
Example:
kent$ sed -n 'H;${x;p}' <(seq 3)
1
2
3
remove the first empty line:
kent$ sed -n 'H;${x;s/[^\n]*\n//;p}' <(seq 3)
1
2
3
Simple put any random string with h i.e 1h;1d, by default it's empty.

Perl: print certain rows based on certain values of column

Hey guys im begginer in Perl programming ,on my list.txt i have a 5 row and 7 columns what i want to do is print certain rows based on the value that the column have for example:
NO. RES REF ERRORS WARNING PROB_E PROB_C
1 k C 0 0 0.240 0.713
2 l C 16 2 0.365 0.568
3 n C 7 4 0.365 0.568
4 f E 0 0 0.613 0.342
I want to print from the column 3,4(error and warnings ) all the rows that have value different than 0. In this case the output to is the row 2 and 3.I hope i make myself clear :) sorry for my poor english.
Try this:
perl -ane 'print if ($F[3] or $F[4])' list.txt

Add leading 0 in sed substitution

I have input data:
foo 24
foobar 5 bar
bar foo 125
and I'd like to have output:
foo 024
foobar 005 bar
bar foo 125
So I can use this sed substitutions:
s,\([a-z ]\+\)\([0-9]\)\([a-z ]*\),\100\2\3,
s,\([a-z ]\+\)\([0-9][0-9]\)\([a-z ]*\),\10\2\3,
But, can I make one substitution, that will do the same? Something like:
if (one digit) then two leading 0
elif (two digits) then one leading 0
Regards.
I doubt that the "if - else" logic can be incorporated in one substitution command without saving the intermediate data (length of the match for instance). It doesn't mean you can't do it easily, though. For instance:
$ N=5
$ sed -r ":r;s/\b[0-9]{1,$(($N-1))}\b/0&/g;tr" infile
foo 00024
foobar 00005 bar
bar foo 00125
It uses recursion, adding one zero to all numbers that are shorter than $N digits in a loop that ends when no more substitutions can be made. The r label basically says: try to do substitution, then goto r if found something to substitute. See more on flow control in sed here.
Use two substitute commands: the first one will search for one digit and will insert two zeroes just before, and the second one will search for a number with two digits and will insert one zero just before. GNU sed is needed because I use the word boundary command to search for digits (\b).
sed -e 's/\b[0-9]\b/00&/g; s/\b[0-9]\{2\}\b/0&/g' infile
EDIT to add a test:
Content of infile:
foo 24 9
foo 645 bar 5 bar
bar foo 125
Run previous command with following output:
foo 024 009
foo 645 bar 005 bar
bar foo 125
Add the max number of leading zeros first, then take this number of characters from the end:
echo 55 | sed -e 's:^:0000000:' -e 's:0\+\(.\{8\}\)$:\1:'
00000055
You seem to have the sed options covered, here's one way with awk:
BEGIN { RS="[ \n]"; ORS=OFS="" }
/^[0-9]+$/ { $0 = sprintf("%03d", $0) }
{ print $0, RT }
I find the following sed approach to pad an integer number with zeroes to 5 (n) digits quite straighforward:
sed -e "s/\<\([0-9]\{1,4\}\)\>/0000\1/; s/\<0*\([0-9]\{5\}\)\>/\1/"
If there is at least one, at most 4 (n-1) digits, add 4 (n-1) zeroes in
front
If there is any number of zeroes followed by 5 (n) digits after the first transformation, keep just these last 5 (n) digits
When there happen to be more than 5 (n) digits, this approach behaves the usual way -- nothing is padded or trimmed.
Input:
0
1
12
123
1234
12345
123456
1234567
Output:
00000
00001
00012
00123
01234
12345
123456
1234567
This might work for you (GNU sed):
echo '1.23 12,345 1 12 123 1234 1' |
sed 's/\(^\|\s\)\([0-9]\(\s\|$\)\)/\100\2/g;s/\(^\|\s\)\([0-9][0-9]\(\s\|$\)\)/\10\2/g'
1.23 12,345 001 012 123 1234 001
or perhaps a little easier on the eye:
sed -r 's/(^|\s)([0-9](\s|$))/\100\2/g;s/(^|\s)([0-9][0-9](\s|$))/\10\2/g'