Linux - GeneralThis 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
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
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.
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.
\| 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.
Ooh simileys. Please wrap your code in code tags (=> the # button at the top of the Wiki editor).
Quote:
Originally Posted by thesunlover
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.
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.
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
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.