LinuxQuestions.org
Review your favorite Linux distribution.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - General
User Name
Password
Linux - General This Linux forum is for general Linux questions and discussion.
If it is Linux Related and doesn't seem to fit in any other forum then this is the place.

Notices


Reply
  Search this Thread
Old 04-05-2018, 07:54 AM   #1
thesunlover
Member
 
Registered: Nov 2009
Posts: 32

Rep: Reputation: 2
One sed command covers 3 patterns ?


Hi,

I need to write a script to delete the following pattern lines from some files.

johnsmith
johnsmith,
johnsmith:

"sed -i /^$username/d $file" doesn't work because users like johnsmith2 will be removed as well.

"sed -i /^$username[,:]/d $file" works for the "johnsmith," and "johnsmith:" cases.

"sed -i /^$username[$,:]/d $file" and "sed -i /^$username[\n,:]/d $file" don't work. The "johnsmith" line cannot be removed.

How can I use one sed command (or something else) to cover all these 3 cases?

Thank you in advance!
 
Old 04-05-2018, 08:01 AM   #2
syg00
LQ Veteran
 
Registered: Aug 2003
Location: Australia
Distribution: Lots ...
Posts: 21,133

Rep: Reputation: 4121Reputation: 4121Reputation: 4121Reputation: 4121Reputation: 4121Reputation: 4121Reputation: 4121Reputation: 4121Reputation: 4121Reputation: 4121Reputation: 4121
sed will honour "|" (or) as well as "$" as an anchor.
 
Old 04-05-2018, 08:05 AM   #3
hazel
LQ Guru
 
Registered: Mar 2016
Location: Harrow, UK
Distribution: LFS, AntiX, Slackware
Posts: 7,601
Blog Entries: 19

Rep: Reputation: 4456Reputation: 4456Reputation: 4456Reputation: 4456Reputation: 4456Reputation: 4456Reputation: 4456Reputation: 4456Reputation: 4456Reputation: 4456Reputation: 4456
Use the question mark. It's a wild multiplier that means once or not at all. Also there is a code for punctuation marks as a class. Look it up. You already seem to know enough about regular expressions to combine these two notations to give you what you want.
 
Old 04-05-2018, 08:10 AM   #4
TB0ne
LQ Guru
 
Registered: Jul 2003
Location: Birmingham, Alabama
Distribution: SuSE, RedHat, Slack,CentOS
Posts: 26,660

Rep: Reputation: 7970Reputation: 7970Reputation: 7970Reputation: 7970Reputation: 7970Reputation: 7970Reputation: 7970Reputation: 7970Reputation: 7970Reputation: 7970Reputation: 7970
Quote:
Originally Posted by thesunlover View Post
Hi,
I need to write a script to delete the following pattern lines from some files.

johnsmith
johnsmith,
johnsmith:

"sed -i /^$username/d $file" doesn't work because users like johnsmith2 will be removed as well.
"sed -i /^$username[,:]/d $file" works for the "johnsmith," and "johnsmith:" cases.
"sed -i /^$username[$,:]/d $file" and "sed -i /^$username[\n,:]/d $file" don't work. The "johnsmith" line cannot be removed.

How can I use one sed command (or something else) to cover all these 3 cases?
I'd suggest you pick up a book on regex's. They are complex, but handy, and in your case can be used to accommodate punctuation. Try:
Code:
sed -i -e '/^johnsmith[[:punct:]]$/d' -e '/^johnsmith$/d'
You don't say if these are just separate lines, or if they're part of larger lines (like "user johnsmith has logged in at noon"), but sed can accommodate multiple -e statements. The first will get anything that starts with johnsmith, followed by ANY punctuation. The second is just johnsmith with a newline. That will leave you with johnsmith2, johnsmithallen, etc.
 
Old 04-05-2018, 08:17 AM   #5
syg00
LQ Veteran
 
Registered: Aug 2003
Location: Australia
Distribution: Lots ...
Posts: 21,133

Rep: Reputation: 4121Reputation: 4121Reputation: 4121Reputation: 4121Reputation: 4121Reputation: 4121Reputation: 4121Reputation: 4121Reputation: 4121Reputation: 4121Reputation: 4121
And in case you haven't guessed, there just might be a few ways of achieving your desired outcome.

How like linux ...
 
Old 04-05-2018, 08:28 PM   #6
MadeInGermany
Senior Member
 
Registered: Dec 2011
Location: Simplicity
Posts: 2,805

Rep: Reputation: 1206Reputation: 1206Reputation: 1206Reputation: 1206Reputation: 1206Reputation: 1206Reputation: 1206Reputation: 1206Reputation: 1206
\| and \? are GNU extensions.
The latter is short for the more universal \{0,1\}
Here it must be followed by $ to ensure it's at the end of the line.
The [ ] should be within quotes to ensure the shell does not try a glob. Best have all sed code in quotes.
Code:
sed -i "/^$username[,:]\{0,1\}$/d" $file

Last edited by MadeInGermany; 04-05-2018 at 08:29 PM.
 
Old 04-06-2018, 08:44 AM   #7
thesunlover
Member
 
Registered: Nov 2009
Posts: 32

Original Poster
Rep: Reputation: 2
Hi, Thank you very much all for your prompt replies that are very helpful !!

This compact one works very well:

sed -i "/^$username[[unct:]]\{0,1\}$/d" $file

The only case that it can't do is "johnsmith ,". Any idea?
 
Old 04-06-2018, 09:01 AM   #8
thesunlover
Member
 
Registered: Nov 2009
Posts: 32

Original Poster
Rep: Reputation: 2
This one is really good "sed -i "/^$username[,:]\{0,1\}$/d" $file". Thanks MadeInGermany !
 
Old 04-06-2018, 09:12 AM   #9
MadeInGermany
Senior Member
 
Registered: Dec 2011
Location: Simplicity
Posts: 2,805

Rep: Reputation: 1206Reputation: 1206Reputation: 1206Reputation: 1206Reputation: 1206Reputation: 1206Reputation: 1206Reputation: 1206Reputation: 1206
Ooh simileys. Please wrap your code in code tags (=> the # button at the top of the Wiki editor).
Quote:
Originally Posted by thesunlover View Post
Hi, Thank you very much all for your prompt replies that are very helpful !!

This compact one works very well:

sed -i "/^$username[[:punct:]]\{0,1\}$/d" $file

The only case that it can't do is "johnsmith ,". Any idea?
You mean: allow an additional space before the punctuation character?

Code:
sed -i "/^$username[[:space:]]*[[:punct:]]\{0,1\}$/d" $file
Like [[:punct:]] that is a class of punctuation characters,
the [[:space:]] is a class of space characters (including Space, TAB, CR, vertical TAB).
There is also [[:blank:]] that is only a space or TAB character.
Followed by a * means it can occur zero or once or many times.
 
1 members found this post helpful.
Old 04-06-2018, 09:17 AM   #10
thesunlover
Member
 
Registered: Nov 2009
Posts: 32

Original Poster
Rep: Reputation: 2
Hi,

A similar question: How to make the following line shorter, or put the three grep to one?

if grep -q ^$username$ $file || grep -q ^$username, $file || grep -q ^$username: $file ; then

Thanks.
 
Old 04-06-2018, 09:18 AM   #11
thesunlover
Member
 
Registered: Nov 2009
Posts: 32

Original Poster
Rep: Reputation: 2
Thank you much again MadeInGermany !
 
Old 04-06-2018, 10:09 AM   #12
MadeInGermany
Senior Member
 
Registered: Dec 2011
Location: Simplicity
Posts: 2,805

Rep: Reputation: 1206Reputation: 1206Reputation: 1206Reputation: 1206Reputation: 1206Reputation: 1206Reputation: 1206Reputation: 1206Reputation: 1206
The same RE applies for grep (but no / / that in sed delimits the RE from other code):
Code:
if grep -q "^$username[:,]\{0,1\}$" $file; then
or
Code:
if grep -q "^$username[[:punct:]]\{0,1\}$" $file; then
or
Code:
if grep -q "^$username[[:blank:]]*[:,]\{0,1\}$" $file; then
or ...

Last edited by MadeInGermany; 04-06-2018 at 10:12 AM.
 
Old 04-06-2018, 12:06 PM   #13
thesunlover
Member
 
Registered: Nov 2009
Posts: 32

Original Poster
Rep: Reputation: 2
Thanks MadeInGermany! Glad to know this good format working for grep as well.

Sorry for my mistake. I failed to make it clearer. Actually the patterns to remove are

johnsmith
johnsmith,John Smith...
johnsmith:John Smith...

So the following code doesn't fulfill the requests perfectly:

Code:
sed -i "/^$username[[:punct:]]\{0,1\}$/d" $file
 
1 members found this post helpful.
Old 04-06-2018, 12:21 PM   #14
TB0ne
LQ Guru
 
Registered: Jul 2003
Location: Birmingham, Alabama
Distribution: SuSE, RedHat, Slack,CentOS
Posts: 26,660

Rep: Reputation: 7970Reputation: 7970Reputation: 7970Reputation: 7970Reputation: 7970Reputation: 7970Reputation: 7970Reputation: 7970Reputation: 7970Reputation: 7970Reputation: 7970
Quote:
Originally Posted by thesunlover View Post
Thanks MadeInGermany! Glad to know this good format working for grep as well.

Sorry for my mistake. I failed to make it clearer. Actually the patterns to remove are

johnsmith
johnsmith,John Smith...
johnsmith:John Smith...

So the following code doesn't fulfill the requests perfectly:
Code:
sed -i "/^$username[[:punct:]]\{0,1\}$/d" $file
I had asked you in post #4 for details about the input strings, and you failed to provide them. You've been given a lot of advice here, along with the solution to this particular problem, but you will have to think about it.

The "$" means "end-of-line". Therefore, "johnsmith,John Smith" won't match "johnsmith$", will it? The solution I gave you in post #4 can easily be modified to include the references about blank spaces as well. You should experiment and find your solution, since all the pieces have already been given to you.
 
Old 04-06-2018, 12:54 PM   #15
MadeInGermany
Senior Member
 
Registered: Dec 2011
Location: Simplicity
Posts: 2,805

Rep: Reputation: 1206Reputation: 1206Reputation: 1206Reputation: 1206Reputation: 1206Reputation: 1206Reputation: 1206Reputation: 1206Reputation: 1206
This can be handled by a \( \) group marker. A following quantifier handles the whole group.
Code:
sed -i "/^$username\([,:].*\)\{0,1\}$/d" $file
It becomes easier if we switch the RE type from BRE (basic regular expression) to ERE (extended regular expression, that is also in egrep or grep -E and in awk and in perl and ...)
Code:
sed -r -i "/^$username([,:].*){0,1}$/d"$file
or even shorter
Code:
sed -r -i "/^$username([,:].*)?$/d" $file
Last but not least, nothing speaks against two simple commands, as TB0ne posted already:
Code:
sed -i "/^$username$/d; /^$username[,:].*$/d" file
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
[SOLVED] understanding sed patterns vincix Linux - Newbie 5 01-08-2018 05:19 AM
sed - using variable values as patterns danielbmartin Programming 7 01-23-2012 02:20 PM
[SOLVED] sed - interleaving remembered patterns danielbmartin Programming 4 01-23-2012 09:10 AM
sed replacing patterns with back quoted command rattlesnakejoe Programming 2 11-18-2009 09:12 AM
Remembering patterns and printing only those patterns using sed bernie82 Programming 5 05-26-2005 05:18 PM

LinuxQuestions.org > Forums > Linux Forums > Linux - General

All times are GMT -5. The time now is 07:46 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration