One-liners to remove lines in which a specific character appears more than x times - sed

I think the title says it all, I'm looking for a one-liner to remove lines of a file in which a specific character, let's say /, appears more than x times - 5, for instance.
Start:
/Bo/byl/apointe
S/ta/ck/ov/er/flo/w
M/oon/
Expected result:
/Bo/byl/apointe
M/oon/
Thank you for your suggestions !

You can use gsub function of awk. gsub return number of successful substitution made. So you can use that as reference to identify number of occurrences of particular character.
awk 'gsub(/\//,"&")<5' file
Updated Based on Ed Morton's suggestion.

This might work for you (GNU sed):
sed 's|/|&|5;T;d' file

All you need is:
awk -F/ 'NF<6' file
Look:
$ cat file
/Bo/byl/apointe
S/ta/ck/ov/er/flo/w
M/oon/
$ awk -F/ 'NF<6' file
/Bo/byl/apointe
M/oon/

I believe sed would be sufficient here. You'll want to look into //d and supply the correct condition. I'm going to try something and update when I have better ideas, you should too :)
Once you find it sed -i /{blah}/d will be enough to change it in the file, but you might want to run it without the -i and pipe it through less first to confirm it's doing what you think it's doing.

This would do :
sed -r '/(\/.*){5}\//d' file

Related

How to remove the last dot from a string in bash?

I have a string as below:
domain="abc-xyz.com."
I need to remove the . at the last so it would look like abc-xyz.com
I tried this and it doesn't work as it is expecting a file
sed 's/\.$//' $domain
Can someone please help me?
Answering OP's issue's fix: Since you are reading input from a variable, then that's not the correct way to pass value from variable to sed what you are using shown in your question(you must be getting No such file or directory error while executing your code).
Try using:
echo "$domain" | sed 's/\.$//'
OR use:
sed 's/\.$//' <<<"$domain"
Ideal way to deal is could be: Try following if you are ok to use parameter expansion as shown by #anubhava sir in comments.
var="${domain%.}"
This might work for you (GNU sed):
sed 's/\(.*\)\./\1/' file
Use greed to locate the last period and replace it by what came before it.

Using Two Regex Strings in SED

I have this text file where I need to first find a string "BEGINNING" and then find a string "HERE" after the first "BEGINNING" but only once. And there can be any amount of strings in between. This must be done with SED commands so no awk. I know I can simply do /BEGINNING/ to find the first one but I don't know how to put the two together in one SED command.
something like this?
$ sed -n '/BEGINNING/,${/HERE/{p;q}}' file
may be supported only by GNU sed, not sure.

I want to append to a line number using sed

I have a file that I need to append to certain lines.
I can get the line numbers and have been able to use sed to print the entry but not to append the entry.
All I need to do is something like
sed -n '$VAR s/$/,nosuid/' > to_file
Just can not get the syntax down.
Thank you.
Try doing this :
sed "$VAR s/$/,nosuid/" > to_file
Like Etan Reisner said in the comments, the quotes should be double quotes.
This might work for you:
sed -n $VAR's/$/,nosuid/' > to_file

Append text to a line on multiple conditions

I am very new to sed so please bear with me... I have a file with contents like
a=1
b=2,3,4
c=3
d=8
.
.
I want to append 'x' to a line which starts with 'c=' and does not contain an 'x'. What I am using right now is
sed -i '/^c=/ s/$/x/'
but this does not cover the second part of my explanation, the 'x' should only be appended if the line did not have it already and hence if I run the command twice it makes the line "c=3xx" which I do not want.
Any help here would be highly appreciated and I know there are a lot of sharp heads around here :) I understand that this can be handled pretty easily through bash but using sed here is a hard requirement.
You can do something like this:
sed -i '/^c=/ {/x/b; s/$/x/}'
Curly brackets are used for grouping. The b command branches to the end of the script (stops the processing of the current line).
b label
Branch to label; if label is omitted, branch to end of script.
Edit: as William Pursell suggests in the comment, a shorter version would be
sed -i '/^c=/ { /x/ !s/$/x/ }'
awk is probably a better choice here as you can easily combine regular expression matches with logical operators. Given the input:
$ cat file
a=1
b=2,3,4
c=3
c=x
c=3
d=8
The command would be:
$ awk '/^c=/ && !/x/ {$0=$0"x"; print $0}' file
a=1
b=2,3,4
c=3x
c=x
c=3x
d=8
Where $0 is the awk variable that contains the current line being read.
This might work for you (GNU sed):
sed -i '/^c=[^x]*$/s/$/x/' file
or:
sed -i 's/^c=[^x]*$/&x/' file

Remove a hyphen from a specific line in a file

I have a data file that needs to have several uniq identifiers stripped of hyphens.
So I have:
(Special_Section "data-values")
and I want to have it replaced with:
(Special_Section "datavalues")
I wanted to use a simple sed find/replace, but the data and values are different each time. Preferably, I'd run this in-place since the file has a lot of other information I want to keep in tact.
Does sed or awk have a way to remove the hyphen from the matched portion only?
Currently I can match with: sed -i 's/Special_Section "[a-zA-Z0-9]*-[a-zA-Z0-9]*"/&/g *myfiles*
But I would like to then run s/-// on & if it's possible.
You seems to be using GNU sed, so something like this might work:
sed -ri '
s/(Special_Section [^-]*)-([^)]*)/\1\2/g
' <your_filename_glob>
does this work?
sed -i '/(Special_Section ".*-.*")/{s/-//}' yourFile
Close - scan for the lines and then substitute on those that match:
sed -i '/Special_Section "[a-zA-Z0-9]*-[a-zA-Z0-9]*"/s/\( "[a-zA-Z0-9]*\)-\([a-zA-Z0-9]*\)"/\1\2/' *myfiles*
You can split that over several lines to avoid the scroll bar in SO:
sed -i '/Special_Section "[a-zA-Z0-9]*-[a-zA-Z0-9]*"/{
s/\( "[a-zA-Z0-9]*\)-\([a-zA-Z0-9]*\)"/\1\2/
}' *myfiles*
And on further thoughts, you can also do:
sed -i 's/\(Special_Section "[a-zA-Z0-9]*\)-\([a-zA-Z0-9]*"\)/\1\2/' *myfiles*
This is more compact. You can add the g qualifier if you need it. Both solutions use the special \(...\) notation to capture parts of the regular expression.