How do I fix 'command not found' that popped out when I tried 'egrep' from a variable? - sh

I wanted to make a program that searches all the lines that contains all the factors given, from a file mydata. I tried to egrep first factor from mydata and save it in a variable a. Then, I tried to egrep the next factor from a and save the result to a again until I egrep all the factors. But when I executed the program, it said
"command not found" in line 14.
if [ $# -eq 0 ]
then
echo -e "Usage: phoneA searchfor [...searchfor]\n(You didn't tell me what you want to search for.)"
else
a=""
for i in $*
do
if [ -z "$a" ]
then
a=$(egrep "$i" mydata)
else
a=$("$a" | egrep "$i")
fi
done
awk -f display.awk "$a"
fi
I expected all the lines including all the factors outputted on the screen in the pattern that I made in display.awk.

$a contains data, not a command. You need to write that data to the pipe.
if [ $# -eq 0 ]
then
printf '%s\n' "Usage: phoneA searchfor [...searchfor]" "(You didn't tell me what you want to search for.)" >&2
exit 1
fi
a=""
for i in "$#"; do
if [ -z "$a" ]; then
a=$(egrep "$i" mydata)
else
a=$(printf '%s' "$a" | egrep "$i")
fi
done
awk -f display.awk "$a"

Related

Bash or Python efficient substring matching and filtering

I have a set of filenames in a directory, some of which are likely to have identical substrings but not known in advance. This is a sorting exercise. I want to move the files with the maximum substring ordered letter match together in a subdirectory named with that number of letters and progress to the minimum match until no matches of 2 or more letters remain. Ignore extensions. Case insensitive. Ignore special characters.
Example.
AfricanElephant.jpg
elephant.jpg
grant.png
ant.png
el_gordo.tif
snowbell.png
Starting from maximum length matches to minimum length matches will result in:
./8/AfricanElephant.jpg and ./8/elephant.jpg
./3/grant.png and ./3/ant.png
./2/snowbell.png and ./2/el_gordo.tif
Completely lost on an efficient bash or python way to do what seems a complex sort.
I found some awk code which is almost there:
{
count=0
while ( match($0,/elephant/) ) {
count++
$0=substr($0,RSTART+1)
}
print count
}
where temp.txt contains a list of the files and is invoked as eg
awk -f test_match.awk temp.txt
Drawback is that a) this is hardwired to look for "elephant" as a string (I don't know how to make it take an input string (rather than file) and an input test string to count against, and
b) I really just want to call a bash function to do the sort as specified
If I had this I could wrap some bash script around this core awk to make it work.
function longest_common_substrings () {
shopt -s nocasematch
for file1 in * ; do for file in * ; do \
if [[ -f "$file1" ]]; then
if [[ -f "$file" ]]; then
base1=$(basename "$file" | cut -d. -f1)
base2=$(basename "$file1" | cut -d. -f1)
if [[ "$file" == "$file1" ]]; then
echo -n ""
else
echo -n "$file $file1 " ; $HOME/Scripts/longest_common_substring.sh "$base1" "$base2" | tr -d '\n' | wc -c | awk '{$1=$1;print}' ;
fi
fi
fi
done ;
done | sort -r -k3 | awk '{ print $1, $3 }' > /tmp/filesort_substring.txt
while IFS= read -r line; do \
file_to_move=$(echo "$line" | awk '{ print $1 }') ;
directory_to_move_to=$(echo "$line" | awk '{ print $2 }') ;
if [[ -f "$file_to_move" ]]; then
mkdir -p "$directory_to_move_to"
\gmv -b "$file_to_move" "$directory_to_move_to"
fi
done < /tmp/filesort_substring.txt
shopt -u nocasematch
where $HOME/Scripts/longest_common_substring.sh is
#!/bin/bash
shopt -s nocasematch
if ((${#1}>${#2})); then
long=$1 short=$2
else
long=$2 short=$1
fi
lshort=${#short}
score=0
for ((i=0;i<lshort-score;++i)); do
for ((l=score+1;l<=lshort-i;++l)); do
sub=${short:i:l}
[[ $long != *$sub* ]] && break
subfound=$sub score=$l
done
done
if ((score)); then
echo "$subfound"
fi
shopt -u nocasematch
Kudos to the original solution for computing the match in the script which I found elsewhere in this site

Remove old Elasticsearch indexes if ELK is installed in docker container using curl

ELK is installed on docker . Due to old logs and indexes server hard disk capacity gets full resulting crash of ELK container.
Run below shell script on docker shell on which elk is installed
#!/bin/bash
DAYSAGO=date --date="200 days ago" +%Y%m%d
ALLLINES=/usr/bin/curl -s -XGET http://127.0.0.1:9200/_cat/indices?v | egrep logstash
echo
echo "THIS IS WHAT SHOULD BE DELETED FOR ELK:"
echo
echo "$ALLLINES" | while read LINE
do
FORMATEDLINE=echo $LINE | awk '{ print $3 }' | awk -F'-' '{ print $2 }' | sed 's/\.//g'
if [ "$FORMATEDLINE" -lt "$DAYSAGO" ]
then
TODELETE=echo $LINE | awk '{ print $3 }'
echo "http://127.0.0.1:9200/$TODELETE"
fi
done
echo
echo -n "if this make sence, Y to continue N to exit [Y/N]:"
read INPUT
if [ "$INPUT" == "Y" ] || [ "$INPUT" == "y" ] || [ "$INPUT" == "yes" ] || [ "$INPUT" == "YES" ]
then
echo "$ALLLINES" | while read LINE
do
FORMATEDLINE=echo $LINE | awk '{ print $3 }' | awk -F'-' '{ print $2 }' | sed 's/\.//g'
if [ "$FORMATEDLINE" -lt "$DAYSAGO" ]
then
TODELETE=echo $LINE | awk '{ print $3 }'
/usr/bin/curl -XDELETE http://127.0.0.1:9200/$TODELETE
sleep 1
fi
done
else
echo SCRIPT CLOSED BY USER, BYE ...
echo
exit
fi

Check whether string starts with "!" in POSIX sh

Trying to create a condition based on whether the line starts with an "!".
Note: this is sh not bash
#!/bin/sh
if [ $line = "!*" ] ;
then
echo "$0: $line has !"
else
echo "$0: $line has no !"
fi
In POSIX test, = performs exact string comparisons only.
Use a case statement instead.
case $line in
"!"*) echo "$line starts with an exclamation mark" ;;
*) echo "$line does not start with an exclamation mark" ;;
esac
If you really want to put this in an if, you can do that:
if case $string in "!"*) true;; *) false;; esac; then
echo "$line starts with an exclamation mark"
else
echo "$line does not start with an exclamation mark"
fi
You can use the standard POSIX parameter substitution syntax.
${var#repl} will remove the repl from the beginning of the content of the $var variable.
So, you'll have:
$ var=test
$ echo ${var#t}
est
$ echo ${var#X}
test
So, in order to have a simple if statement to check if a variable starts with a string (! in your case), you can have:
#!/bin/sh
if test "$line" = "${line#!}"; then
echo "$0: $line has no !"
else
echo "$0: $line has !"
fi
PS: test ... is equivalent to [ ... ], so the above script is exactly the same as
#!/bin/sh
if [ "$line" = "${line#!}" ]; then
echo "$0: $line has no !"
else
echo "$0: $line has !"
fi
Could be as simple as echo "$STR" | cut -c -1.
#!/bin/sh
STR="!abcd"
if [ "!" = $(echo "$STR" | cut -c -1) ]; then
echo "true"
fi

Trying to clone a ksh function with little modification with a one liner perl

I've a short ksh script that is often generated automatically. However, it's missing some stuff and I want to be able to "fix it" like I want by running a simple 1 liner perl to sed it.
Let say that the ksh contains the following function:
foo()
{
/some/command param1
if [[ $? -eq 0 ]]
then
/some/other/command stop param1
fi
/some/command param2
if [[ $? -eq 0 ]]
then
/some/other/command stop param2
fi
#...
}
and what I really want looks like this
foo_force()
{
/some/command param1
if [[ $? -eq 0 ]]
then
/some/other/command stop -f param1
fi
/some/command param2
if [[ $? -eq 0 ]]
then
/some/other/command stop -f param2
fi
#...
}
foo()
{
/some/command param1
if [[ $? -eq 0 ]]
then
/some/other/command stop param1
fi
/some/command param2
if [[ $? -eq 0 ]]
then
/some/other/command stop param2
fi
#...
foo_force
}
So far I've been able to get something "close", ie 2 perl commands, which would be ok with me. However, the second command only replace the last stop by a -f stop... which is not what I'm looking for.
/usr/bin/perl -i -pe "BEGIN{undef $/;}; s/^(foo)(\(\)\n{.*\n)}/\1_force\2}\n\n\1\2\t\1_force\n}/gms" /tmp/foo.ksh
/usr/bin/perl -i -pe "BEGIN{undef $/;}; s/^(foo\(\)\n{.* stop)( .*\n})/\1 -f\2/gms" /tmp/foo.ksh
This might work for you (GNU sed):
sed -i '/^foo()/{:a;$!N;/\n}/!ba;h;s/^foo/&_force/;s/stop /&-f /g;s/$/\n/p;g;s/\n}/\n\n foo_force&/}' /file
Using perl
perl -0777 -i -pe '
s{(^foo\(\).*?\n\})}{
my $foo = my $force = $1;
$foo =~ s/\}$/ foo_force()\n\}/;
$force =~ s/^foo\K/_force/;
$force =~ s/ stop \K/-f /g;
"$foo\n$force"
}mse;
' /tmp/foo.ksh

Resolve name by inode in current direcory

How can I resolve the name by the given inode in the current directory in the following script that prints all filenames of symlinks pointing to a specified file that is passed as an argument to the script. The list should be sorted by ctime.
#!/usr/bin/ksh
IFS="`printf '\n\t'`"
USAGE="usage: symlink.sh <file>"
get_ctime() {
perl -se 'use File::stat; $file=lstat($filename); print $file->ctime' -- -filename="$1"
}
stat_inode() {
perl -se 'use File::stat; $file=stat($filename); if (defined $file) { print $file->ino; }' -- -filename="$1"
}
lstat_inode() {
perl -se 'use File::stat; $file=lstat($filename); if (defined $file) { print $file->ino; }' -- -filename="$1"
}
if [ $# -eq 0 ]; then
echo "$USAGE"
exit 1
fi
FILE_NAME="$1"
FILE_INODE=$(stat_inode "$FILE_NAME")
if [ ! -e "$FILE_NAME" ]; then
echo "no such file \"$FILE_NAME\""
exit 1
fi
for LINK in ./* ./.[!.]* ;do
if [ -L "$LINK" ]; then
TARGET_INODE=$(stat_inode "$LINK")
if [ ! -z "$TARGET_INODE" ]; then
if [ "$FILE_INODE" -eq "$TARGET_INODE" ]; then
echo $(get_ctime "$LINK") $(lstat_inode "$LINK");
fi
fi
fi
done | sort -nk1 | awk '{print $2}'
Basically, I'd like to pipe awk to some kind of lookup function like this: | awk ' ' | lookup
I'd really appreciate if someone suggested a more elegant way to accomplish the task.
OS: SunOS 5.10
Shell: KSH
Something like this?
$ find . -maxdepth 1 -inum 2883399
./.jshintrc
$
or:
$ echo 2883399 | xargs -IX find . -maxdepth 1 -inum X
./.jshintrc
$