I have three files foo1.txt, foo2.txt and foo3.txt, which contain the following lines
# foo1.txt
JOBDONE
and
# foo2.txt
Execution halted
and
# foo3.txt
Execution halted
JOBDONE
I have been able find the ones with both JOBDONE and Execution halted using:
find ./foo*.txt | xargs grep -l 'Execution halted' | xargs grep -l "JOBDONE"
But have not been able to find those files which have JOBDONE or Execution halted but not both. I have tried:
find ./foo*.txt | xargs grep -lv "JOBDONE" | xargs grep -l "Execution halted"
find ./foo*.txt -exec grep -lv "JOBDONE" {} \; | xargs grep -l "Execution halted"
but have been incorrectly (to my understanding) returning
./foo2.txt
./foo3.txt
What is wrong with my understanding of how xargs and exec works with grep and how do I use grep or another portable command to select those logs that have JOBDONE but not Execution halted or vice versa?
Here is an gnu awk (gnu due to multiple characters in RS)
awk -v RS="#-#-#" '/JOBDONE/ && /Execution halted/ {print FILENAME}' foo*
foo3.txt
Setting RS to something that is not in the file, it will thread all lines as one.
Then test if the long line has both string, and if yes, print filename
Related
I'm trying to pipe the output of a find command to a perl one-liner to replace a line that ends with ?> with RedefineForDocker::standardizeXmlmc() but for some reason the value isn't being replaced. I've checked the output of the find command and it is performing as expected, and I've double checked my regex and it should match.
find . -name *.php -exec ggrep -Ezl 'class XmlMethodCall.*([?]>)$' {} \; \
| xargs perl -ewpn -i.bak2 \
"s/[?]>\s*?$/RedefineForDocker::standardizeXmlmc()\n/gm"
I get no warnings and no indication that it isn't working, the backups are created, but the file remains unchanged. The list of matched files run from the find command is below.
./swsupport/clisupp/trending/services/data.helpers.php
./swsupport/clisupp/_bpmui/arch/service/data.helpers.php
./swsupport/clisupp/_bpmui/itsm/service/data.helpers.php
./swsupport/clisupp/_bpmui/itsm_default/service/data.helpers.php
./webclient_code/php/session.php
./webclient_code/service/storedquery/helpers.php
./php/_phpinclude/itsm/xmlmc/xmlmc.php
./php/_phpinclude/itsmf/xmlmc/xmlmc.php
./php/_phpinclude/itsm_default/xmlmc/xmlmc.php
Here is an example of one of the files it should match
https://regex101.com/r/BUoCif/1
Run your perl command as this:
perl -i.bak2 -wpe 's/\?>\h*$/RedefineForDocker::standardizeXmlmc()\n/gm'
Order of command line option is important here.
Full pipeline should be like this:
find . -name '*.php' -exec ggrep -PZzl '(?ms)class XmlMethodCall.*\?>\h*$' {} + |
xargs -0 perl -i.bak2 -wpe 's/\?>\h*$/RedefineForDocker::standardizeXmlmc()\n/gm'
Note use -Z option in grep and -0 option in xargs to address issues with filenames with whitespaces etc.
I know this sort of question has been asked many times before, but I'm running into an odd circumstance where my feeble brain forgot to include a \ while calling $\sim$ in some markdown files. I need to go through and replace all instances of $sim$ with $\sim$. My code is running but not actually replacing any of the words that I want. Here are some variations I have tried:
grep -rl '\$sim\$' . | xargs sed -i 's/\$sim\$/$\sim$/g'
grep -rlF '$sim$' . | xargs sed -i 's/\$sim\$/$\sim$/g'
grep -rlF '$sim$' . | xargs sed -i 's/$sim$/$\sim$/g'
grep -rlF '$sim$' . | xargs sed -i '' -e 's/$sim$/$\sim$/g'
And other odd variations on a theme. The code just runs with no output but when I check the files nothing has changed. I figure this is either a sed issue (I'm macOS) or a regex issue.
Like this :
grep -rlF '$sim$' | xargs sed -i 's/$sim\$/$\\sim$/g'
for MacOsX :
grep -rlF '$sim$' | xargs sed -i '' 's/$sim\$/$\\sim$/g'
sed -i changes files in place, however you aren't telling sed to operate on any files. You are giving sed its input on stdin.
What you want is something like
find . -type f -exec sed -i 's/\$sim\$/$\\sim\$/g' {} \;
I'm writing a quick program that lists all of the soft/symbolic links in the working directory to a file which is given in argument 1. I'm aware that I need to use grep in order to do so, but in general I have difficulty figuring out how to write the regular expression. In this case, it is especially difficult due to the fact that a variable ($argv[1]) is involved.
The (poorly-written) line of code in question is as follows:
ls -l | xargs grep '-> $argv[1]'
My intention with this was to catch all of the lines that contained the -> and the specified file, such as
link1 -> file
link2 -> file
and so on. Is there any way that I can use grep to accomplish this?
What kind of language is $argv[1]? The (POSIX) Bourne Shell doesn't support arrays. Arguments to scripts and functions are referenced by $1, $2 and so on.
In order for grep to not treat the first hyphen in the pattern as an option, use -- to signal the end of options. Next, there is no parameter substitution in single quotes, only in double qouotes. Putting it all together, this might work:
set somename # Sets $1 to somename
ls -l | xargs grep -- "-> $1"
If your grep doesn't understand --, try
ls -l | xargs grep ".*-> $1"
Below script can find only the soft / symbolic link files and list only if the argument found on those files,
# cat sygrep.sh
#!/bin/bash
if [ $# -eq 0 ]
then
echo "No arguments supplied"
else
for a in `find . -type l` ; do grep -irl '$1' $a ; done
fi
Output:
# ./sygrep.sh
No arguments supplied
# ./sygrep.sh root
./mytest.sh
I wrote a little script which prints the names of files containing problematic character sequences.
#!/bin/bash
# Finds all files in the repository that contain
# undesired characters or sequences of characters
pushd .. >/dev/null
# Find Windows newlines
find . -type f | grep -v ".git/" | grep -v ".gitmodules" | grep -v "^./lib" | xargs grep -l $'\r'
# Find tabs (should be spaces)
find . -type f | grep -v ".git/" | grep -v ".gitmodules" | grep -v "^./lib" | xargs grep -l $'\t'
# Find trailing spaces
find . -type f | grep -v ".git/" | grep -v ".gitmodules" | grep -v "^./lib" | xargs grep -l " $"
popd >/dev/null
I'd line to combine this into one line, i.e. by having grep look for \r OR \t or trailing spaces. How would I construct a regex to do this? It seems that for escape characters a special sequence needs to be used ($'\X') and I'm not sure how to combine these...
I'm running OS X, and am looking for a solution that works on both BSD and GNU based systems.
find . -type f | grep -E -v ".git/|.gitmodules|^./lib" | xargs grep -E -l '$\r|$\t| $'
Not certain that '$\r|$\t| $' will work quoted that way, with a simple test on my system it seemed to work.
I'm using the -E (extended reg-exp) to grep, that allows 'OR'ing together multiple search targets.
Older Unix-en may or maynot support the -E option, so if you get an error message flagging that, replace all grep -E with egrep.
I hope this helps.
I am working on a bash script.
grep -R -l "image17" *
image17 will change to some other number when I go through my loop. When I execute the grep above, I get back the following:
slides/_rels/slide33.xml.rels
I need to put slide33 in a variable because I want to use that to rename the file named image17.jpeg to be called slide33.jpeg. I need something to check for the above format and parse out starting at slide and ending with the numbers.
Another problem is the grep statement could come up with multiple results rather than one. I need a way to check to see how many results and if one do one thing and if more than one do another.
Here is what I have so far. Now I just need to put the grep as a variable and check to see how many times it happens and if it is one then do the regular expression to get the filename.
#!/bin/sh IFS=$'\n'
where="/Users/mike/Desktop/test"
cd "${where}"
for file in $(find * -maxdepth 0 -type d)
do
cd "${where}/${file}/images"
ls -1 | grep -v ".png" | xargs -I {} rm -r "{}"
cd "${where}/${file}/ppt"
for images in $(find * -maxdepth 0 -type f)
do
if [ (grep -R -l "${images}" * | wc -l) == 1 ]
then
new_name=grep -R -l "slide[0-9]"
fi
done
done
i=0
while [ $i -lt 50 ]
do
grep -R -l "image${i}"
done
something like this might help
Or, to detect similar structured words you can do
grep -R -l "slide[0-9][0-9]"
or you can do
grep -R -l "slide[0-9]+"
to match atleast one digit and atmost any number
Check man grep for more in the "REGULAR EXPRESSION" section
this will match words starting with "slide" and ending with exactly two numbers
grep -c does count the number of matches, but does not print the matches. I think you should count the lines to detect the number of lines which grep matched and then execute the conditional statement.