grep: No such file or directory for line in file - bash

I'm trying to grep every line within a file, and for every match echo PASS, for every non match echo FAIL. I am getting a "no such file or directory" error, it seems to be trying to grep a file instead of the line I am passing within my loop?
File:
$ cat new.txt
TLS_RSA_WITH_AES_128_GCM_SHA256
TLS_RSA_WITH_AES_128_CBC_SHA256
TLS_RSA_WITH_AES_128_CBC_SHA
TLS_RSA_WITH_3DES_EDE_CBC_SHA
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
Failing script:
#!/bin/bash
while IFS= read -r line
do
if grep -P 'TLS_RSA' $line; then
echo "PASS."
else
echo "FAIL."
fi
done < "new.txt"
When running a normal grep command against the file this is the output (expected):
$ grep -P 'TLS_RSA' new.txt
TLS_RSA_WITH_AES_128_GCM_SHA256
TLS_RSA_WITH_AES_128_CBC_SHA256
TLS_RSA_WITH_AES_128_CBC_SHA
TLS_RSA_WITH_3DES_EDE_CBC_SHA

I suggest to replace
if grep -P 'TLS_RSA' $line; then
with
if grep -q 'TLS_RSA' <<< "$line"; then
to feed grep's stdin with content of a variable.

#!/bin/bash
while IFS= read -r line; do
grep -q 'TLS_RSA' <<< $line && echo "PASS."|| echo "FAIL."
done < "new.txt"
You need to replace the $line with <<< $line.
Also for the sake of cleaner code, you can also do away with the if statement and make it into a single line.

You can also use awk as an alternative to looping in a script
awk '{ print "grep -o \"TLS_RSA\" "$0" && echo -e \""$0"\nPASS\" || echo -e \""$0"\nFAIL\"" }' new.txt | bash
This prints the grep command for each line (file) in the new.txt file and then pipes the command through to bash to execute
As an alternative, you can use awk's built in system funtion and so:
awk '{ system("grep -o \"TLS_RSA\" "$0" && echo -e \""$0"\nPASS\" || echo -e \""$0"\nFAIL\"") }' new.txt
NOTE - You need to be careful with command indirection examples such as these. It is important that you print and verify the command (i.e. run the command with piping through to bash in the first example) before executing the actual commands.

You can do the same without grep but just built-in POSIX shell features:
#!/usr/bin/env sh
while IFS= read -r line
do
case $line in
*TLS_RSA*) printf %s\\n PASS.;;
*) printf %s\\n FAIL.;;
esac
done <new.txt

Related

Shell - Execute commands in external file between two patterns

I have got a question. How should I proceed and make this code print out and execute curl examples that I have on my external file?
How I want it to work is to match the pattern, get text between the patterns (without the pattern) and then execute it.
Is there way to do this?
Thanks for the help.
read -p "Enter a word: " instance
testfile=test.txt
case $instance in
loresipsum)
sed -n '/^loremipsum1/,${p;/^loremipsum2/q}' $testfile \
| while read -r line; do
makingcurlCall=$(eval "$line")
echo "makingcurlCall"
done < $testfile ;;
foobar)
sed -n '/^foobar1/,${p;/^foobar2/q}' $testfile \
| while read -r line; do
makingcurlCall=$(eval "$line")
echo "makingcurlCall"
done < $testfile ;;
*)
printf 'No match for "%s"\n' ":instance"
esac
Text file looks like this
loremipsum1
curl example1
curl example2
curl example3
loremipsum2
foobar1
curl foo
curl bar
curl foo
foobar2
You cannot have the while loop read from both the output of sed and directly from the file. Your current code is ignoring the output from sed and reading directly from the file. Perhaps refactor it like:
#!/bin/sh
instance=${1-loresipsum}
testfile=test.txt
case $instance in
loresipsum) sed -n '/^loremipsum1/,/^loremipsum2/p' "$testfile";;
foobar) sed -n '/^foobar1/,/^foobar2/p' "$testfile";;
*) echo "Error: no match" >&2;;
esac \
| sed -e 1d -e '$d' -e '/^\s*$/d' | while read -r line; do
# makingcurlCall=$(eval "$line")
echo "makingcurlCall: $line"
done

Concatenate String and Variable in Shell Script

Content of file is:
#data.conf
ip=127.0.0.1
port=7890
delay=10
key=1.2.3.4
debug=true
Shell Script:
#!/bin/bash
typeset -A config
config=()
config_file_path="./data.conf"
cmd="java -jar ./myprogram.jar"
#This section will read file and put content in config variable
while read line
do
#echo "$line"
if echo $line | grep -F = &>/dev/null
then
key=$(echo "$line" | cut -d '=' -f 1)
config[$key]=$(echo "$line" | cut -d '=' -f 2)
echo "$key" "${config["$key"]}"
fi
done < "$config_file_path"
cmd="$cmd -lh ${config["ip"]} -lp ${config["port"]} -u ${config["debug"]} -hah \"${config["key"]}\" -hap ${config["delay"]}"
echo $cmd
Expected output:
java -jar myprogram.jar -lh 127.0.0.1 -lp 7890 -u true -hah "1.2.3.4" -hap 10 -b
Output:
Every time some unexpected o/p
Ex. -lp 7890rogram.jar
Looks like it is overwriting same line again and again
In respect to the comments given and to have an additional automatic data cleansing within the script, you could have according How to convert DOS/Windows newline (CRLF) to Unix newline (LF) in a Bash script? and Remove carriage return in Unix
# This section will clean the input config file
sed -i 's/\r$//' "${config_file_path}"
within your script. This will prevent the error in future runs.

Grep command returns nothing in shell script

When I try to extract rows that are matched string which are in another file.But the grep command returns nothing.
#!/bin/bash
input="export.txt"
file="filename.csv"
val=`head -n 1 $file`
echo $val>export.csv
cat export.txt | while read line
do
val=`echo $line | tr -d '\n'`
echo $val
valu=`grep $val $file`
echo $valu
done
You can simply do this :
grep -f list.txt input.txt
Which will extract all the lines from input which match any word from list.txt.
If for some reason you want to save each match, you can do it in a Bash array as :
IFS=$'\n' read -d '' -a values <<< "$( grep -f list.txt input.txt )"
And then you can print a certain match as :
echo "${values[1]}"
Regards!

How can I tokenize $PATH by using awk?

How can I tokenize $PATH by using awk?
I tried 3 hours, but it totally screwed out.
#!/bin/bash
i=1
while true; do
token=$($echo $PATH | awk -F ':' '{print $"$i"}')
if [ -z "$token" ]; then
break
fi
((i++))
if [ -a "$TOKEN/$1" ]; then
echo "$TOKEN/$1"
break
fi
break
done
When I run this code, I got
/home/$USERID/bin/ff: line 6: /home/$USERID/bin:/usr/local/symlinks:/usr/local/scripts:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/home/$USERID/bin: No such file or directory
How can I change my program?
What are you trying to do?
This will let you iterate against the individual paths:
echo $PATH | tr ':' '\n' | while read line; do echo $line; done
As #SiegeX notes, an even shorter version works
echo $PATH | while read -d ':' line; do echo $line; done
Do the whole thing in awk
#!/bin/bash
awk -v addPath="$1" 'BEGIN{RS=":";ORS=addPath "\n"}{$1=$1}1' <<< $PATH
Proof of Concept
$ addPath="/foo"
$ awk -v addPath="$addPath" 'BEGIN{RS=":";ORS=addPath "\n"}{$1=$1}1' <<< $PATH
/usr/local/bin/foo
/usr/bin/foo
/bin/foo
/usr/games/foo
/usr/lib/java/bin/foo
/usr/lib/qt/bin/foo
/usr/share/texmf/bin/foo
./foo
/sbin/foo
/usr/sbin/foo
/usr/local/sbin/foo
I think simple tr : \\n would suffice. Pipe it with sed 's#$#blabla#g' to add something to the lines and that's it.
You don't need to use external tools such as awk or tr to tokenize the PATH. Bash is capable of doing so:
#!/bin/sh
IFS=:
for p in $PATH
do
if [ -a "$p/$1" ]; then
echo "$p/$1"
break
fi
done
The IFS is a bash built-in variable which bash use as an input field separator (IFS).

How to replace a line in bash

How can I replace a line that starts with "string1" with "string2 lala" using Bash script?
use the sed utility
sed -e 's/^string1.*/string2 lala/'
or
sed -e 's/^string1.*/string2 lala/g'
to replace it every time it appears
using bash,
#!/bin/bash
file="myfile"
while read -r line
do
case "$line" in
string1* ) line="string2 lala"
esac
echo "$line"
done <"$file" > temp
mv temp $file
using awk
awk '/^string1/{$0="string2 lala"}1' file

Resources