&& gets ignored when trying to grep several files [closed] - if-statement

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about a specific programming problem, a software algorithm, or software tools primarily used by programmers. If you believe the question would be on-topic on another Stack Exchange site, you can leave a comment to explain where the question may be able to be answered.
Closed 1 year ago.
Improve this question
Im trying to grep in several different files, using different type of matching. But for some reason it seems it ignores the arguments after &&.
$ grep -E -i "err|warn" h2_backups.log storagefolder_backups.log
$ grep -E -i 'err|warn' exports.log imports.log
exports.log:err
$ grep -E -i "err|warn" h2_backups.log storagefolder_backups.log && grep -E -i 'err|warn' exports.log imports.log
$ grep -E -i 'err|warn' exports.log imports.log && grep -E -i "err|warn" h2_backups.log storagefolder_backups.log
exports.log:err
As you can see, the first grep contains no error but the second grep does. On the third line I used the grep with no error match first, and this ignores everything after &&. On the forth line I've switched places of the greps and now I get a match (however it probably still ignores everything after &&).
Using && seems to work on my other servers. Any thoughts what might cause this?

This is the normal behaviour as per the short-circuit evaluation. You are doing command1 && command2. If command1 returns False, then command2 will not be evaluated because the whole condition is already False.
See in a very simple example:
$ cat a
hello
grep "hello" returns something, while grep "bye" does not:
$ grep "hello" a
hello
$ grep "bye" a
$
Hence the behaviour when adding && echo "yes":
$ grep "hello" a && echo "yes"
hello
yes
$ grep "bye" a && echo "yes"
$

Related

How to express variable in sed? [duplicate]

This question already has answers here:
Is it possible to escape regex metacharacters reliably with sed
(4 answers)
Closed 2 years ago.
$ VAR="this is working well"
$ sed -i "s/$/,$VAR/" my.txt
$ VAR="this/got/error"
$ sed -i "s/$/,$VAR/" my.txt
sed: -e expression #1, char 12: unknown option to `s
I have to put various kind of strings to $VAR.
Sometimes $VAR is not working with sed. Bcoz of special character.
How can I solve this problem with sed or regular expression?
Thank u in advance.
sed does not have the concept of variables, and the variable you're using is being interpreted by the shell before sed even sees it. Because of this, if you want to use some sort of variable that can handle arbitrary text, you need to use a different tool which can do this.
For example, you could do this using Perl:
$ perl -i 's/$/,$ENV{VAR}/g' my.txt
or you could do it using awk and a temporary file:
$ awk '{ sub(/$/, "," ENVIRON["VAR"]); print }' my.txt > temp && mv temp my.txt
Note that using sed -i, regardless of whether it has this problem or not, is not portable. On macOS, you must use sed -i '', but that syntax does not work on Linux. The perl -i invocation is portable to all systems using Perl, as would be an equivalent technique using ruby -i.
Whilst sed tutorials typically use / as the search/replace delimiters, you can use many other symbols as delimiters. For example s/one/two/ could also be written as s|one|two or as s#one#two.
So - to solve your particular problem, the solution is simple - use a different delimiter.
$ cat file.txt
1
2
3
4
$ VAR="this is working well"
$ sed 's/$/,'"$VAR"'/' file.txt
1,this is working well
2,this is working well
3,this is working well
4,this is working well
$ VAR="this/got/error"
$ sed 's|$|,'"$VAR"'|' file
1,this/got/error
2,this/got/error
3,this/got/error
4,this/got/error
$

Two seemingly identical sed commands, one works, the other doesn't. Can you tell me why? [duplicate]

This question already has answers here:
Difference between single and double quotes in Bash
(7 answers)
Closed 7 years ago.
There's something I'm having trouble understanding concerning sed behavior.
sed -n "/pattern/,$p" < input.inp > output.out
gives the following error
sed: -e expression n°1, caractère 10: `,' inattendue
(my system is in french).
sed -n '/pattern/,$p' < input.inp > output.out
Works fine
I've personnally used commands like
sed -n "/begin/,/end/p" < input.inp > output.out
with both single or double quotes, and they work just fine.
In case it's useful, I have sed version: sed (GNU sed) 4.2.2
In double quotes, the shell, not sed, will evaluate $p. Since you probably haven't set a variable named p, sed will only see /pattern/,. To prevent this from happening, you'd need to escape the $ to the shell, by writing \$ instead:
sed -n "/pattern/,\$p" < input.inp > output.out
(You can imagine that using single quotes is a lot easier on the eyes and brain, unless you need shell variables in your expression.)

RegEx to get the pattern for a output string in shell script

I run the command grep to get certain output and store it into a variable. The output of grep command is:
5.3.1-6.2011171513.ASMOS6
but I need to only parse out 5.3.1-6 and store that version in a variable. How can I do that?
What about this?
TEXT=5.3.1-6.2011171513.ASMOS6
RES=$(echo $TEXT | cut -d. -f-3)
We cut the string on . and then get the first 3 pieces.
With awk
RES=$(echo $TEXT | awk -F. 'OFS=FS {print $1,$2,$3}')
OFS=FS meaning we get the delimiter to print that was defined with -F.
As you tag says linux, I'll assume that you have a modern grep that supports the -o option.
You can do
var=$(grep -o 'regex' file)
To capture just the regex to a variable.
Unfortunately, I don't understand the problem you're having getting just 5.3.1-6, you have to edit your question to show us the regex youare currently using.
IHTH

How to use grep to extract a substring? [duplicate]

This question already has answers here:
Closed 10 years ago.
The community reviewed whether to reopen this question 7 months ago and left it closed:
Original close reason(s) were not resolved
Possible Duplicate:
extract regexp result from string and write it to a variable
Here is my command :
grep -E '\*[[:space:]]+FIN[[:space:]]+([^)]+?)') myfile
It outputs :
FIN (SUCCESS)
And I would like it outputs only :
SUCCESS
How can I tell grep to do it ?
You can pipe the output of your grep command to the awk command.
grep -E '*[[:space:]]+FIN[[:space:]]+([^)]+?)') myfile | awk '{print $2}'
I am not sure how to do that with grep alone, as it is not really tailored to that exact use case. Since you are on a platform where grep is, use pipes to your advantage when you can have one command solve part of the problem, and another command the other part.
grep is not capable of outputting a single capture group, but you can use sed to do it instead:
sed 's/\*[[:space:]]\+FIN[[:space:]]\+(\([^)]\+\))/\1/g' file
If you use ack then you can use match groups and the --output switch:
ack '\*\s+FIN\((.+?)\)' --output='$1' myfile

Sed substitution not doing what I want and think it should do

I have am trying to use sed to get some info that is encoded within the path of a file which is passed as a parameter to my script (Bourne sh, if it matters).
From this example path, I'd like the result to be 8
PATH=/foo/bar/baz/1-1.8/sing/song
I first got the regex close by using sed as grep:
echo $PATH | sed -n -e "/^.*\/1-1\.\([0-9][0-9]*\).*/p"
This properly recognized the string, so I edited it to make a substitution out of it:
echo $PATH | sed -n -e "s/^.*\/1-1\.\([0-9][0-9]*\).*/\1/"
But this doesn't produce any output. I know I'm just not seeing something simple, but would really appreciate any ideas about what I'm doing wrong or about other ways to debug sed regular expressions.
(edit)
In the example path the components other than the numerical one can contain numbers similar to the numeric path component that I listed, but not quite the same. I'm trying to exactly match the component that that is 1-1. and see what some-number is.
It is also possible to have an input string that the regular expression should not match and should product no output.
The -n option to sed supresses normal output, and since your second line doesn't have a p command, nothing is output. Get rid of the -n or stick a p back on the end
It looks like you're trying to get the 8 from the 1-1.8 (where 8 is any sequence of numerics), yes? If so, I would just use:
echo /foo/bar/baz/1-1.8/sing/song | sed -e "s/.*\/1-1\.//" -e "s/[^0-9].*//"
No doubt you could get it working with one sed "instruction" (-e) but sometimes it's easier just to break it down.
The first strips out everything from the start up to and including 1-1., the second strips from the first non-numeric after that to the end.
$ echo /foo/bar/baz/1-1.8/sing/song | sed -e "s/.*\/1-1\.//" -e "s/[^0-9].*//"
8
$ echo /foo/bar/baz/1-1.752/sing/song | sed -e "s/.*\/1-1\.//" -e "s/[^0-9].*//"
752
And, as an aside, this is actually how I debug sed regular expressions. I put simple ones in independent instructions (or independent part of a pipeline for other filtering commands) so I can see what each does.
Following your edit, this also works:
$ echo /foo/bar/baz/1-1.962/sing/song | sed -e "s/.*\/1-1\.\([0-9][0-9]*\).*/\1/"
962
As to your comment:
In the example path the components other than the numerical one can contain numbers similar to the numeric path component that I listed, but not quite the same. I'm trying to exactly match the component that that is 1-1. and see what some-number is.
The two-part sed command I gave you should work with numerics anywhere in the string (as long as there's no 1-1. after the one you're interested in). That's because it actually deletes up to the specific 1-1. string and thereafter from the first non-numeric). If you have some examples that don't work as expected, toss them into the question as an update and I'll adjust the answer.
You can shorten you command by using + (one or more) instead of * (zero or more):
sed -n -e "s/^.*\/1-1\.\([0-9]\+\).*/\1/"
don't use PATH as your variable. It clashes with PATH environment variable
echo $path|sed -e's/.*1-1\.//;s/\/.*//'
You needn't divide your patterns with / (s/a/b/g), but may choose every character, so if you're dealing with paths, # is more useful than /:
echo /foo/1-1.962/sing | sed -e "s#.*/1-1\.\([0-9]\+\).*#\1#"