[SOLVED] Shell Script parse string/match what isn't there
ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
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.
So I've been searching for a while, I'm a bit tired, and finally giving in to writing a post.
I'm writing a shell script (BASH) to do some system file configuration and I need to try and identify if extraneous variables/data have been added to a string...and can't think for the life of me how to do so.
For example within /etc/ssh/sshd_config I have the following line:
Code:
AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
Now the acceptable values for that line are anything that starts with LC.
So my first move to match that line within sshd_config is:
That will return the line I mentioned above which is great...but I want to take it a step further. I need to isolate that extraneous data. A grep -v doesn't work because it needs to match a line that has LC and I can't think of an awk command off the top of my head that will show me a match of everything on the line that doesn't match LC*.
In my example, what I'm wanting as a final returned value is just the LANG portion of the string but there are a lot of possible values so I can't just search for LANG because then I'd miss if say someone put XMODIFIERS or any other variable there.
Expected magic expression:
Code:
grep -i AcceptEnv /etc/ssh/sshd_config | grep -i LC | <awk/grep show matches within string that are not LC*>
Any ideas?
Last edited by JHO5; 01-26-2012 at 01:28 PM.
Reason: Added further clarification
awk '(tolower($1) == "acceptenv") {
for (i = 2; i <= NF; i++)
if ($i != "LANG" &&
substr($i,1,3) != "LC_")
print $i
}' /etc/ssh/sshd_config
You can easily add similar checking for other directives by duplicating the rule. In awk, each rule is applied once for each input record (line by default).
NF is the number of fields (by default, fields are words, anything non-whitespace separated by whitespace). The loop ignores the first field, since that is the AcceptEnv directive. If the field is not LANG, and does not start with LC_, it is printed.
Now, to match your original problem description, you would of course use
Code:
awk '(tolower($1) == "acceptenv") {
for (i = 2; i <= NF; i++)
if (substr($i,1,3) != "LC_")
print $i
}' /etc/ssh/sshd_config
instead.
Last edited by Nominal Animal; 01-26-2012 at 02:54 PM.
Looks like it works - I modified it slightly to be just:
Code:
awk '(tolower($1) == "acceptenv") {
for (i = 2; i <= NF; i++)
if (substr($i,1,3) != "LC_")
print $i
}' /etc/ssh/sshd_config
That way I do catch the LANG flag (since that's not a LC* flag)
Thanks! (of course if others have other solutions, that works as well)
As a reference, I ran your code against a RHEL6 box and it returned:
LANG
LANGUAGE
XMODIFIERS
whereas on my default RHEL5 install, it would have just returned LANG (hence why I wanted to be able to capture potential additional flags without knowing what the available flags were).
@Cedrik: This is not criticism, I really want to know: If you saw that stanza, how long would it take for you to parse and grasp what it actually does? It took me almost a minute. Well, half a minute at least. Am I just slow to read perl?
@Cedrik: This is not criticism, I really want to know: If you saw that stanza, how long would it take for you to parse and grasp what it actually does? It took me almost a minute. Well, half a minute at least. Am I just slow to read perl?
I'm slow as well - but then again, I don't regularly program in perl. For me, it was mostly the matching AcceptEnv coming at the end that threw me when I first looked at it.
@Cedrik: This is not criticism, I really want to know: If you saw that stanza, how long would it take for you to parse and grasp what it actually does? It took me almost a minute. Well, half a minute at least. Am I just slow to read perl?
I doesnt take 1 minute !
The input line is autosplited in @F array with -a perl option
The print command line is only executed if input line matches /AcceptEnv/i
(which means match AcceptEnv ignoring case, like grep -i)
@F[1..$#F] : list from @F array, that starts at element 2 and ends at last element of @F
(like in your code, i starts at 2)
grep {!/^LC_/} : return a list of elements extracted from previous list that don't match /^LC_/
map {print "$_\n"} : print each element of list returned by grep with an added newline
(had to do this since perl print function does not add newline by default unlike awk print)
Actually, the issue for me is the structure, not the (sub)expressions. In most programming languages I get an intuitive mental image of the code flow just by looking at a function or a method, without really reading it, within the first second or two.
With Perl, I have to understand each (sub)expression first, then the structure becomes evident. (Although I do avoid Perl nowadays, a decade ago I did have to work with the innards of a couple of Perl projects. I guess I was scarred for life, not because of the language, but because of the projects. So it is not like I'm in any way new to Perl.)
Thanks for your insight, though. I find it very interesting that you chose to describe the subexpressions in right-to-left order. It would be very interesting to do some statistical research (perhaps even here on LQ), and see if certain features, like tendency to use distinct language features such as unless, has correlation to programming language preference or proficiency.
Returning back to the original topic, I do believe that seeing and discussing differing alternate solutions to a problem is always fruitful. Therefore I repeat: thank you.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.