I need to pass a specific value from shell to a AWK script file but i dont know i cant do it.
#! /bin/bash
if [ "$2" = "-C" ] && [ "$3" != "" ]; then
awk -f SpecCity.awk $1
elif [ "$2" = "-C" ] && [ "$3" = "" ]; then
awk -f CityOnly.awk $1
fi
I need to pass the value $3 to AWK which will compare it with the a file i will point but i cant do it.
Any idea how to do it ?
Thankyou
You should be able to use "awk -v". For example, "awk -v city=$3..."
Newer versions of awk should also support the "ENVIRON[]" array.
Both options are discussed here:
http://unix-school.blogspot.com/2011/09/awk-passing-arguments-or-shell.html
Related
I have written the following Bash script. Its role is to check its own name, and in case of nonexistent extension , to amend ".sh" with sed. Still I have error "missing target file..."
#!/bin/bash
FILE_NAME="$0"
EXTENSION=".sh"
FILE_NAME_MOD="$FILE_NAME$EXTENSION"
if [[ "$0" != "FILE_NAME_MOD" ]]; then
echo mv -v "$FILENAME" "$FILENAME$EXTENSION"
cp "$0" | sed 's/\([^.sh]\)$/\1.sh/g' $0
fi
#!/bin/bash
file="$0"
extension=".sh"
if [ $(echo -n $file | tail -c 3) != $extension ]; then
mv -v "$file" "$file$extension"
fi
Important stuff:
-n flag suppress the new line at the end, so we can test for 3 chars instead of 4
When in doubt, always use set -x to debug your scripts.
Try this Shellcheck-clean code:
#! /bin/bash -p
file=${BASH_SOURCE[0]}
extension=.sh
[[ $file == *"$extension" ]] || mv -i -- "$file" "$file$extension"
See choosing between $0 and BASH_SOURCE for details of why ${BASH_SOURCE[0]} is better than $0.
See Correct Bash and shell script variable capitalization for details of why file is better than FILE and extension is better than EXTENSION. (In short, ALL_UPPERCASE names are dangerous because there is a danger that they will clash with names that are already used for something else.)
The -i option to mv means that you will be prompted to continue if the new filename is already in use.
See Should I save my scripts with the .sh extension? before adding .sh extensions to your shell programs.
Just for fun, here is a way to do it just with GNU sed:
#!/usr/bin/env bash
sed --silent '
# match FILENAME only if it does not end with ".sh"
/\.sh$/! {
# change "FILENAME" to "mv -v FILENAME FILENAME.sh"
s/.*/mv -v & &.sh/
# execute the command
e
}
' <<<"$0"
You can also make the above script output useful messages:
#!/usr/bin/env bash
sed --silent '
/\.sh$/! {
s/.*/mv -v & &.sh/
e
# exit with code 0 immediately after the change has been made
q0
}
# otherwise exit with code 1
q1
' <<<"$0" && echo 'done' || echo 'no changes were made'
I have a file hoge.txt like this:
case $1 in
[ $input = "q" ] && exit
if [ -s $filename ]
if [ ! -f $1 -o -f $2 ]
echo $list
rm -f ${BKDIR}
BKDIR=/${HOME}/backup
And I want to find all alphabetic variables, exclude every parameters like "$1" and output to a new file like this:
$input
$filename
$list
The best i can do now is
cat hoge.txt | awk '{for(i=1;i<=NF;i++){ if($i=="$/[a-zA-Z]/"){print $i} } }'
But it doesn't return any results.
You don't need to use Awk for such a trivial example, just use extended regular expressions support using the -E flag and print only the matching word using -o
grep -Eo '\$[a-zA-Z]+' file
produces
$input
$filename
$list
and write to a new file using the re-direction(>) operator
grep -Eo '\$[a-zA-Z]+' file > variablesList
(or) saving two key strokes (suggested in comments below) with enabling the case insensitive flag with -i
grep -iEo '\$[a-z]+' file
I have a strange behavior in the bash script that I don't understand.
Basically in the code below I try to escape meta-characters...
while IFS=, read _type _content; do
if [ -z "$patternfilter" ]; then
if [ "$_type" == "rex" ]; then
patternfilter="$_content"
elif [ "$_type" == "txt" ]; then
patternfilter="`echo "$_content" | sed -re 's/([-^[{}()*+/.,;?$|#\\])/\\\1/g' -e 's/]/\\]/g'`"
fi
else
if [ "$_type" == "rex" ]; then
patternfilter="$patternfilter|$_content"
elif [ "$_type" == "txt" ]; then
patternfilter="$patternfilter|`echo "$_content" | sed -re 's/([-^[{}()*+/.,;?$|#\\])/\\\1/g' -e 's/]/\\]/g'`"
fi
fi
done < $patternfile
The outpout give me the following :
blabal\1bla\1blabla\1toto\1com
Instead of :
blabal\(bla\)blabla\[toto\]\.com
If I enter directly in the console the code it works ... I miss something but I don't know what.
[root]# patternfilter="blabal(bla)blabla[toto].com"
[root]# echo "$patternfilter" | sed -re 's/([-^[{}()*+/.,;?$|#\\])/\\\1/g' -e 's/]/\\]/g'
blabal\(bla\)blabla\[toto\]\.com
You cannot reliably escape characters in sed as whether or not a character needs to be escaped is context sensitive. Also, the shell is an environment from which to call tools. The standard UNIX tool to manipulate text is awk. Just have your shell call awk to do everything. By the way, your use of `...` instead of $(...) will interpret double escapes and your use of read without -r will expand escapes.
SInce awk can operate on strings as well as REs you almost certainly won't have to escape anything since the usual reason to escape chars is to try to make your tool that only works on REs work on strings, which is an impossible task.
If you tell us what you're trying to do with patternfilter along with some sample input and expected output, we can show you how to do it simply and robustly.
Check the next script:
while IFS=, read -r line; do
result1="`echo "$line" | sed -re 's/([-^[{}()*+/.,;?$|#\\])/\\\1/g' -e 's/]/\\]/g'`"
echo "1=$result1="
result2="$(echo "$line" | sed -re 's/([-^[{}()*+/.,;?$|#\\])/\\\1/g' -e 's/]/\\]/g')"
echo "2=$result2="
done <<'EOF'
blabal(bla)blabla[toto].com
EOF
prints:
1=blabal\1bla\1blabla\1toto]\1com=
2=blabal\(bla\)blabla\[toto\]\.com=
instad of the backticks use $(), as in the result2=... line. (and always use -r for read -r)
You can escape simpler, with the printf "%q" such,
while IFS=, read _type _content; do
res=$(printf "%q" "$_content")
echo "==$res=="
done <<EOF
txt,blabal(bla)blabla[toto].com
EOF
what prints
==blabal\(bla\)blabla\[toto\].com==
But, read #EdMorton's answer.
If I have a string:
s='path/to/my/foo.txt'
and an array
declare -a include_files=('foo.txt' 'bar.txt');
how can I check the string for matches in my array efficiently?
You could loop through the array and use a bash substring check
for file in "${include_files[#]}"
do
if [[ $s = *${file} ]]; then
printf "%s\n" "$file"
fi
done
Alternately, if you want to avoid the loop and you only care that a file name matches or not, you could use the # form of bash extended globbing. The following example assumes that array file names do not contain |.
shopt -s extglob
declare -a include_files=('foo.txt' 'bar.txt');
s='path/to/my/foo.txt'
printf -v pat "%s|" "${include_files[#]}"
pat="${pat%|}"
printf "%s\n" "${pat}"
#prints foo.txt|bar.txt
if [[ ${s##*/} = #(${pat}) ]]; then echo yes; fi
For an exact match to the file name:
#!/bin/bash
s="path/to/my/foo.txt";
ARR=('foo.txt' 'bar.txt');
for str in "${ARR[#]}";
do
# if [ $(echo "$s" | awk -F"/" '{print $NF}') == "$str" ]; then
if [ $(basename "$s") == "$str" ]; then # A better option than awk for sure...
echo "match";
else
echo "no match";
fi;
done
i am trying to write a code where i have used an IF statement.
here I am trying to compare 2 string that are obtained by using an awk statement.
Please help me...if this is possible.
if [ "awk '/$search/ {print $3}' rpt1.txt" -eq "awk '/$search/ {print $3}' rpt2.txt" ]
Sure, using $() or ``.
if [ $(awk '/$search/ {print $3}' rpt1.txt) -eq $(awk '/$search/ {print $3}' rpt2.txt) ]
If you want string comparison rather than numeric you probably want = instead of -eq though.
Might read better if you made a function too:
search_report() {
awk "/$1/ { print \$3 }" $2
}
if [ $(search_report $search rpt1.txt) -eq $(search_report $search rpt2.txt) ]
...
You can capture stdout into a variable like this:
variable=$(command)
Try this
rpt1=$(awk '/$search/ {print $3}' rpt1.txt)
rpt2=$(awk '/$search/ {print $3}' rpt2.txt)
if [ "${rpt1}" == "${rpt2}" ]; then
echo "match";
fi
The operator -eq works with integers only, that's why I used == instead.
More about capturing stdout
http://www.cyberciti.biz/faq/unix-linux-bsd-appleosx-bash-assign-variable-command-output/
This is a excellent summary of operators in bash
http://tldp.org/LDP/abs/html/comparison-ops.html