Create grep command dynamic and run from variable - grep

I am trying to create regex dynamicly and then run it, this is part of script
...
param="egrep $2 $1"
shift
shift
while [ $# -ne 0 ]
do
param="$param""|egrep $1"
shift
done
$param // here i get error
...
But echo for $param seems to me ok
.P F1 a b c // run script
egrep a F1| egrep b| egrep c
What should I do in order to run $param correctly?

try
eval $param

try: eval $cmd

Related

Print file name if grep finds multiple occurrences of a string in file, else exit on failure

File1 contains
hello
hello
I need to write a grep command to print the filename if this file contains more than one "hello". Otherwise, I need grep to exit on failure.
So far I have
grep -c "hello" File1 | grep -v :0
but it outputs
2. How do I get the desired output, which should either be filename File1 or no output at all (from what I understand, no match is a non zero exit code for grep)
with GNU grep for -z:
grep -lz 'hello.*hello' file
e.g.:
$ seq 15 | grep -lz '3.*3'
(standard input)
$ echo $?
0
$ seq 5 | grep -lz '3.*3'
$ echo $?
1
Like this:
#!/bin/bash
count=$(grep -c "hello" "$1")
if ((count > 1)); then
echo "$1"
else
exit 1
fi
Usage:
chmod +x script.sh
./script.sh File1
Explanations:
((...)) is an arithmetic command, which returns an exit status of 0 if the expression is nonzero, or 1 if the expression is zero. Also used as a synonym for "let", if side effects (assignments) are needed. See http://mywiki.wooledge.org/ArithmeticExpression
Using perl in a shell:
perl -0 -le '
my $filename = $ARGV[0];
print $filename if grep { /hello\nhello/ } <>
' file

Grep search for binary data

Why does this command work
echo -ne "\x74\x79\xf4"|grep -aPo "\x74\x79"
and this doesn't?
echo -ne "\x74\x79\xf4"|grep -aPo "\x74\x79\xf4"
The following will work:
echo -ne "\x74\x79\xC3\xB4" | grep -aPo "\x74\x79\xf4"
# ^^^^^^^
echo -ne "\x74\x79\u00F4" | grep -aPo "\x74\x79\xf4"
# ^^^^^^
The \xF4 is not a single byte, it consists of two bytes, C3 and B4. Thus, to encode it properly in the echo command, you need to use \xC3\xB4 sequence.
With \u00F4, you specify the code unit.

RedHat Memory Used High

Looking for some help if you will..
I have a virtual machine on RedHat 6.5 with 32gb memory.
A free is showing 24.6gb used, 8.2gb free. Only 418mb is cached, 1.8gb buffers.
Executed a top and sorted by virtual used, and I can only account for about 6gb of that 24.6gb used.
A "ps aux" doesn't show any processes that could be taking the memory.
I am flummoxed and looking for some advice on where I can look to see whats taking the memory?
Any help would be appreciated.
Below Bash Script will help you figure out which application is consuming how much of memory.
#!/bin/bash
# Make sure only root can run our script
if [ "$(id -u)" != "0" ]; then
echo "This script must be run as root" 1>&2
exit 1
fi
### Functions
#This function will count memory statistic for passed PID
get_process_mem ()
{
PID=$1
#we need to check if 2 files exist
if [ -f /proc/$PID/status ];
then
if [ -f /proc/$PID/smaps ];
then
#here we count memory usage, Pss, Private and Shared = Pss-Private
Pss=`cat /proc/$PID/smaps | grep -e "^Pss:" | awk '{print $2}'| paste -sd+ | bc `
Private=`cat /proc/$PID/smaps | grep -e "^Private" | awk '{print $2}'| paste -sd+ | bc `
#we need to be sure that we count Pss and Private memory, to avoid errors
if [ x"$Rss" != "x" -o x"$Private" != "x" ];
then
let Shared=${Pss}-${Private}
Name=`cat /proc/$PID/status | grep -e "^Name:" |cut -d':' -f2`
#we keep all results in bytes
let Shared=${Shared}*1024
let Private=${Private}*1024
let Sum=${Shared}+${Private}
echo -e "$Private + $Shared = $Sum \t $Name"
fi
fi
fi
}
#this function make conversion from bytes to Kb or Mb or Gb
convert()
{
value=$1
power=0
#if value 0, we make it like 0.00
if [ "$value" = "0" ];
then
value="0.00"
fi
#We make conversion till value bigger than 1024, and if yes we divide by 1024
while [ $(echo "${value} > 1024"|bc) -eq 1 ]
do
value=$(echo "scale=2;${value}/1024" |bc)
let power=$power+1
done
#this part get b,kb,mb or gb according to number of divisions
case $power in
0) reg=b;;
1) reg=kb;;
2) reg=mb;;
3) reg=gb;;
esac
echo -n "${value} ${reg} "
}
#to ensure that temp files not exist
[[ -f /tmp/res ]] && rm -f /tmp/res
[[ -f /tmp/res2 ]] && rm -f /tmp/res2
[[ -f /tmp/res3 ]] && rm -f /tmp/res3
#if argument passed script will show statistic only for that pid, of not – we list all processes in /proc/ #and get statistic for all of them, all result we store in file /tmp/res
if [ $# -eq 0 ]
then
pids=`ls /proc | grep -e [0-9] | grep -v [A-Za-z] `
for i in $pids
do
get_process_mem $i >> /tmp/res
done
else
get_process_mem $1>> /tmp/res
fi
#This will sort result by memory usage
cat /tmp/res | sort -gr -k 5 > /tmp/res2
#this part will get uniq names from process list, and we will add all lines with same process list
#we will count nomber of processes with same name, so if more that 1 process where will be
# process(2) in output
for Name in `cat /tmp/res2 | awk '{print $6}' | sort | uniq`
do
count=`cat /tmp/res2 | awk -v src=$Name '{if ($6==src) {print $6}}'|wc -l| awk '{print $1}'`
if [ $count = "1" ];
then
count=""
else
count="(${count})"
fi
VmSizeKB=`cat /tmp/res2 | awk -v src=$Name '{if ($6==src) {print $1}}' | paste -sd+ | bc`
VmRssKB=`cat /tmp/res2 | awk -v src=$Name '{if ($6==src) {print $3}}' | paste -sd+ | bc`
total=`cat /tmp/res2 | awk '{print $5}' | paste -sd+ | bc`
Sum=`echo "${VmRssKB}+${VmSizeKB}"|bc`
#all result stored in /tmp/res3 file
echo -e "$VmSizeKB + $VmRssKB = $Sum \t ${Name}${count}" >>/tmp/res3
done
#this make sort once more.
cat /tmp/res3 | sort -gr -k 5 | uniq > /tmp/res
#now we print result , first header
echo -e "Private \t + \t Shared \t = \t RAM used \t Program"
#after we read line by line of temp file
while read line
do
echo $line | while read a b c d e f
do
#we print all processes if Ram used if not 0
if [ $e != "0" ]; then
#here we use function that make conversion
echo -en "`convert $a` \t $b \t `convert $c` \t $d \t `convert $e` \t $f"
echo ""
fi
done
done < /tmp/res #this part print footer, with counted Ram usage echo "--------------------------------------------------------" echo -e "\t\t\t\t\t\t `convert $total`" echo "========================================================" # we clean temporary file [[ -f /tmp/res ]] && rm -f /tmp/res [[ -f /tmp/res2 ]] && rm -f /tmp/res2 [[ -f /tmp/res3 ]] && rm -f /tmp/res3
I am going to take a wild stab at this. Without having access to the machine or additional information troubleshooting this will be difficult.
The /tmp file system is special in that it exists entirely in memory. There are a couple others that are like this but /tmp is a special flower. Check the disk usage on this directory and you may see where your memory is getting consumed. ( du -sh /tmp )

Select text between two paterns in huge html file?

1st issue : My code is working only if grep take constant pattern like this :
echo "$s" | grep -oP '(?<=class="A3">).*(?=</a>)'
2nd issue : assigning output to a variable not working too
Here is my script :
#!/bin/sh
filename="data.txt"
Ptr_ValidChannel="><a title=\"Id: "
Ptr_ChannelNameStart="<class=\"A3\">"
Ptr_ChannelNameEnd="</a>"
while read -r line
do
case "$line" in
# working 100%
#*$Ptr_ValidChannel*) echo "$line" | grep -oP '(?<=class="A3">).*?(?=</a>)' ;;
# not working
#*$Ptr_ValidChannel*) echo $line | grep -oP '(?<=$Ptr_ChannelNameStart).*?(?=$Ptr_ChannelNameEnd)' ;;
# not working
*$Ptr_ValidChannel*) myvar=$(echo $line | grep -oP '(?<=$Ptr_ChannelNameStart).*?(?=$Ptr_ChannelNameEnd)') ;;
esac
done < "$filename"
echo $var_name
exit
To simplify things the data.txt content is :
<TD WIDTH="15%"><a title="Id: I24 NEWS" class="A3">I24 News Français</a><br /><font color="#555555"> <a title="Sporadic or full 16/9 transmission"><img src="/169.gif"></a>
In my system the command :
ls -la /bin/sh
output is :
/bin/sh -> dash
best regards.
PS. NO BASH CODE PLEASE. ONLY SH.
After reading this article: dash as bin sh. i figured out what to do to make my code work correctly and more portable:
#! /bin/sh
filename='data.txt'
Ptr_ValidChannel='><a title="Id: '
Ptr_ChannelNameStart='class="A3">'
Ptr_ChannelNameEnd='</a>'
while read -r line
do
case "$line" in
*"$Ptr_ValidChannel"*) var_name=$(printf %s "$line" | grep -oP '(?<='"$Ptr_ChannelNameStart"').*?(?='"$Ptr_ChannelNameEnd"')'); printf %s "$var_name"; printf '\n'; ;;
esac
done < "$filename"
exit
Thank you for your comments
best reagrds.

grep returns No such file or directory in Script but works manually

What i wanted was to make a little Script that makes a grep over files that successfully passed another grep.
Here is that i wrote:
#!/bin/bash -f
if (( $# != 3 ))
then
echo "Usage: $0 <directory> <grep1> <grep2>"
exit 1
fi
dir=$1
grep1=$2
grep2=$3
files=`grep -Ril "$grep1" $dir`
for file in $files; do
grep -iH "$grep2" $file
done
so this works, in case the directory is a specific one.
But It doesnt work in the way i wanted to use it:
./grepIfSucceededGrep.sh /mnt/logs/\*/20130929/\* test1 test2
grep: /mnt/logs/*/20130929/*: No such file or directory
But when i enter the command manually it works perfectly. Must have to do something with the asterisk.
grep -Ril "segment1" /mnt/logs/*/20130929/*
/mnt/logs/1111/20130929/000033.00.log
/mnt/logs/1112/20130929/000033.00.log
/mnt/logs/1113/20130929/154852.00.log
/mnt/logs/1114/20130929/171227.00.log
Why?! :( just searched for 2 hours to get a workarround but had no fix for that issue.
Do you really need a script to achieve what you need? You can say:
find /path -type f -exec sh -c "grep -iq string1 {} && grep -iq string2 {} && echo {}" \;
This would list the files in /path and subdirectories that contain both string1 and string2.
If you need to put it into a script so that you could pass parameters, say:
find $1 -type f -exec sh -c "grep -iq $2 {} && grep -iq $3 {} && echo {}" \;
within a file, say myfind.sh that could be invoked by saying sh myfind.sh /my/path/to/search firststring secondstring.

Resources