Remove all lines before a match with sed - sed

I'm using sed to filter a list of files. I have a sorted list of folders and I want to get all lines after a specific one. To do this task I'm using the solution described here which works pretty well with any input I tried but it doesn't work when the match is on the first line. In that case sed will remove all lines of the input
Here it's an example:
$ ls -1 /
bin
boot
...
sys
tmp
usr
var
vmlinuz
$ ls -1 / | sed '1,/tmp/d'
usr
var
vmlinuz
$ ls -1 / | sed '1,/^bin$/d'
# sed will delete all lines from the input stream
How should I change the command to consider also the limit case when first line is matched by regexp?
BTW sed '1,1d' correctly works and remove the first line only.

try this (GNU sed only):
sed '0,/^bin$/d'
..output is:
$sed '0,/^bin$/d' file
boot
...
sys
tmp
usr
var
vmlinuz

This sed command will print all lines after and including the matching line:
sed -n '/^WHATEVER$/,$p'
The -n switch makes sed print only when told (the p command).
If you don't want to include the matching line you can tell sed to delete from the start of the file to the matching line:
sed '1,/^WHATEVER$/d'
(We use the d command which deletes lines.)

you can also try with :
awk '/searchname/{p=1;next}{if(p){print}}'
EDIT(considering the comment from Joe)
awk '/searchname/{p++;if(p==1){next}}p' Your_File

I would insert a tag before a match and delete in scope /start/,/####tag####/.

Related

Selecting records on base of first character

I have a file which contains the following records
+aaaa
+bbbb
cccc-123
-dddd
eeee+789
-fff+456
ggg
Now I want to keep only the records if the first character is a "+" or "-" sign
so the (new) file should look like this
+aaaa
+bbbb
-dddd
-fff+456
Can this be done via a grep or sed command ?
Try this:
grep '^\[+-\]' myfile.txt
or
grep '^[+-]' myfile.txt
Depending on your flavour of grep
This might work for you (GNU sed):
sed '/^[+-]/!d' file
or:
sed -n '/^[+-]/p' file
In the first solution: if the first character of the line is not + or - delete the line.
In the second solution: if the first character of the line is + or - print it.

sed replace 1 line in file with all lines in file

Lets say I have a line #SYM
I need to replace it with all lines from file1.txt
Is it possible to do that with sed?
I have tried sed 's/#SYM/file1.txt/' updater
But that doesn't work, because I need to load file1.txt as string, and I do not know how to do that.
EDIT: I believe that there could be a way to do it in a shell script somehow.
EDIT2: I also just tried this:
#!/bin/bash
value=$(<tools/symlink)
sed -i 's/#SYM/$value/' META-INF/com/google/android/updater-script
Use r command:
sed -e '/#SYM/ {r tools/symlink' -e 'd}' META-INF/com/google/android/updater-script
/#SYM/ {r tools/symlink if a line contains #SYM, append the contents of tools/symlink
d} then delete the matching line
the two commands are separated using -e option because everything after r is considered as part of filename
Add the -i option once you are satisifed that it is working

Grep and replace the character from grepped result

I am trying to grep the line from file and then from $1 I am trying to change the character.
eg
cat file1.txt
Surjit
Shilpa
cchiku
end of file
I tried and grepped the line which start with s.
grep -e "S"
Then I want to replace the 4th character to x for all grepped result in the file1.txt
I tried
sed -i "s/./x/4" file1.txt
How can I do this only for grepped results?
You can use the sed '/pattern/s/find/replace/' file syntax:
sed '/^S/s/./x/4' file
# ^^ ^^^^^^^
# | replace the 4th character with x
# |
# on lines starting with S
With your file:
$ sed '/^S/s/./x/4' file
Surxit
Shixpa
cchiku
end of file
Note I am using /^S/ as a pattern to match lines starting with S, because if you just say /S/ it will match any line containing S. The anchor ^ indicates the beginning of the line.
An alternative to fedorqui's answer is to include the starting with S condition into the pattern itself:
sed 's/^\(S..\)./\1x/' file
The command matches lines starting with S and puts the S and the following two characters into a matching group. In the replacement part the content of the matching group will get reused and next character after it will get replaced by x.
awk -v FS="" -v OFS="" '/^S/{$4="x"}1' infile
Surxit
Shixpa
cchiku
end of file

Better way to fix mocha lcov output using sed

Due to the know prob of mocha-lcov-mocha breaking file paths, I need to fix the current output paths that looks like this:
SF:Vis/test-Guid.coffee
SF:Vis/Guid.coffee
SF:Vis/test-Vis-Edge.coffee
SF:Vis/Vis-Edge.coffee
into
SF:test/Vis/test-Guid.coffee
SF:src/Vis/Guid.coffee
SF:test/Vis/test-Vis-Edge.coffee
SF:src/Vis/Vis-Edge.coffee
I'm not very good with sed, but I got it to work using:
mocha -R mocha-lcov-reporter _coverage/test --recursive | sed 's,SF:,SF:src/,' | sed s',SF.*test.*,SF:test//&,' | sed s',/SF:,,' | sed s',test/src,test,' | ./node_modules/coveralls/bin/coveralls.js
which is basically doing 4 sed commands in sequence
sed 's,SF:,SF:src/,'
sed s',SF.*test.*,SF:test//&,'
sed s',/SF:,,'
sed s',test/src,test,'
my question is if there is a way to do with this one sed command, or use another osx/linux command line tool
Initially put "src/" after every ":" and then if "test" is found on the line replace "src" with "test":
$ sed 's,:,:src/,;/test/s,src,test,' file
SF:test/Vis/test-Guid.coffee
SF:src/Vis/Guid.coffee
SF:test/Vis/test-Vis-Edge.coffee
SF:src/Vis/Vis-Edge.coffee
You could put all the sed commands in a file, one line per command, and just use "sed -e script". But if you just want it on a single command-line, separate with semicolons. This works for me:
sed 's,SF:,SF:src/,;s,SF.*test.*,SF:test//&,;s,SF:,,;s,test/src/,test,'
sed command
sed '\#test#!{s#SF:Vis/#SF:src/Vis/#g};\#SF:Vis/test#{s#SF:Vis/test#SF:test/Vis/test#g};' my_file
Here is an awk version:
awk -F: '/SF/ {$0=$1FS (/test/?"test/":"src/")$2}1' file
SF:test/Vis/test-Guid.coffee
SF:src/Vis/Guid.coffee
SF:test/Vis/test-Vis-Edge.coffee
SF:src/Vis/Vis-Edge.coffee
How it works:
awk -F: ' # Set field separator to ":"
/SF/{ # Does line start with "SF"?
$0=$1FS (/test/?"test/":"src/")$2 # Recreat String by adding "test" if line contains "test", else "src"
}
1 # Print all lines
' file # read the file

Simple SED statement to truncate everything after first instance of underscore AFTER # sign

Input:
ab_cd#yahoo.co.uk_DN_135.PNG
ef_gh#gmail.com_ST_19_1_9.jpg
Required Output:
ab_cd#yahoo.co.uk
ef_gh#gmail.com
I'm looking for a SED statement to do the above.
Essentially I would like everything from and including the first underscore character AFTER the # sign to be removed from the output.
I'm sorry I only have basic knowledge of programming. I'm on a Windows machine [I've found a SED editor] from here
and use it modify simple strings in a batch file from the Windows shell.
Many thanks
give this a try:
sed 's/_[^#]*$//' file
it worked here with your input:
kent$ cat f
ab_cd#yahoo.co.uk_DN_135.PNG
ef_gh#gmail.com_ST_19_1_9.jpg
kent$ sed 's/_[^#]*$//' f
ab_cd#yahoo.co.uk
ef_gh#gmail.com
This can be a way:
$ sed -r 's/(.*#[^_]*).*/\1/' file
ab_cd#yahoo.co.uk
ef_gh#gmail.com
It catches all the text before #, after it and up to _. Then, it prints it back, getting rid of everything coming from _.
Explanation
Matching group: given a sed 's/something/back/' command, whatever you "catch" in the part, can be enclosed in parenthesis so that you can refer back to it with \1 (first match), \2 (2nd match), and up to \9.
$ cat file
hello33bye
hello44goodbye
hello55yeah
$ sed 's/hello([0-9]*).*/\1/g' a
33
44
55
So (.*#[^_]*).* means: catch a block of text followed by # and followed with any character appart from _. Then, catch the rest of the text.
Finally, print the catched block back.
To be sure we are not matching a _ within the domain:
sed -r 's/(.*#[^\.]*[^_]*).*/\1/' file
^^^^^^
catch a dot before catching an underscore
Test
$ cat a
ab_cd#yahoo.co.uk_DN_135.PNG
ef_gh#gmail.com_ST_19_1_9.jpg
aaa#gma_il.com_ST_BB
aaa#gma_il.com
$ sed -r 's/(.*#[^\.]*[^_]*).*/\1/' a
ab_cd#yahoo.co.uk
ef_gh#gmail.com
aaa#gma_il.com
aaa#gma_il.com
Here is an awk version. (awk is normal more easy to understand than sed)
cat file
ab_cd#yahoo.co.uk_DN_135.PNG
ef_gh#gmail.com_ST_19_1_9.jpg
test#home_net.com_BO_22.jpg
awk -F\. '{NF--;split($NF,a,"_");$NF=a[1]}1' OFS=\. file
ab_cd#yahoo.co.uk
ef_gh#gmail.com
test#home_net.com
It removes the last field when split by ., then divide last field by _ and replace it by first part of it.