grep text by function parameter in bash - bash

There is a file name as pkg_list
a-1.2b-1.tar.gz
c-2.5b-1.tar.gz
a xx-1.4.txz
a$xx-1.4.txz
中文-3.txz
xx-3.2-2.tar.gz
xxy-1.3.tar.gz
My bash function can input package name like 'xx'
pkg_find() { # <pkg_name> as $1
grep "^$1-[0-9]*" pkg_list
}
pkg_find xx # wish it return xx-3.2-2.tar.gz
I know I can not pass $1 directly into pkg_find, what's the correct method?
[SOLVED]
In this case, because $1 is enclosed by double quote, I found even regex meta chars could pass as parameter.

What you're doing looks right to me.
What isn't working?
I tried the code in your question, and pkg_find xx displays ‘xx-3.2-2.tar.gz’ — which you say is the output you were hoping for.

You can pass $1 directly to pkg_find
pkg_find() { # <pkg_name> as $1
grep "^$1-[0-9]*" pkg_list
}
pkg_find "$1"
In the main body, $1, $2, .. are the script arguments, you get from the command line or another calling script. In a shell function they refer to the function arguments.
When you call this on the command line
sh pkg_find.sh xx
you will get
xx-3.2-2.tar.gz

Your code and your question seem to me to ask for different things, you want to either/both of:
pass a function parameters: Passing parameters to a Bash function
return a string from a function: shell script function return a string
$1, $2 etc at the top-level of a script are the script parameters; within a function they
are set to the function parameters, or unset if there are no parameters.

Related

passing bash array separated by comma

i have bash script which do some function with website domains like following
#!/usr/bin/env bash
domain="$1";
function A(){
ping $domain -c 4
}
function B(){
host $domain
}
A;
B;
and when i run this script by doing ./script.sh whateverdomain.com it works well.
BUT i heard that with array i can run the script against some of domains seperated by comma for example.
like ./script.sh domain1.com,domain2.com and it will excute the whole script function against the first one then the second one and i tried the following code.
my_arr=($(echo $DOMAIN | tr "," "\n"))
d=$(for domain in "${my_arr[#]}" ;
do echo $domain
done)
pingme(){
ping -c 4 $d
}
but it hanging and not passing each domain to variable $d
so i need to define array as function and when i run the script it pass domain and execute the script functions then repeat the whole script against the second domain and so on like.
#!/usr/bin/env bash
domain="$1";
function myarray(){
# the array function which will pass the domains one by one
}
function A(){
ping $domain -c 4
}
function B(){
host $domain
}
myarray;
A;
B;
Converting comments into an answer.
The natural way to write shell scripts is to pass the arguments separately:
./script.sh domain1.com domain2.com
and iterate over the elements of "$#" in the script, passing the domain names explicitly to the function (as shown) — global variables are just as problematic in shell scripts as in other programming languages.
#!/usr/bin/env bash
A() { ping "$1" -c 4; }
B() { host "$1"; }
for domain in "$#"
do
A $domain
B $domain
done
If you must use the comma-separated argument, then use:
domains=($(echo "$1" | tr "," "\n"))
pingme() { ping "$1" -c 4; }
for domain in "${domains[#]}"
do
pingme $domain
done
and (as before) the function should process $1, not a global variable.
Inside a function, $1 is the first argument passed to the function, not what's passed to the script as a whole.
Note that in the original code, none of the semicolons is needed. In the code I wrote, the semicolons before the close braces are needed because I lazily wrote the functions on a single line (because they are so simple — I would probably not use functions for such simple commands, especially as they're each only invoked once in the script). If they were spread over three or four lines, the semicolons would not be needed.
A()
{
ping "$1" -c 4
}
Also, you don't need to use the keyword function — and it is generally regarded as a bad idea to do so. As Charles Duffy noted in a comment, the Bash Hackers wiki indicates you should not use function.

How to create a directory in a function

Editing:
I'm trying to build a simple function that print out a name, then creates a directory. I'm new at building function in bash, so I have the below script that didn't work:
dest_path=/home/all/todo
line="name"
mkdir_for_name() {
echo $1
mkdir $2
}
mkdir_for_name $name
mkdir_for_name $dest_path/$name
What is wrong with that syntax?
Since you are using echo so I believe you want to print directory name; and off course you need to pass 2 arguments to your function. May be call your function in following way. In this way you need not to change your code.
mkdir_for_name "$name" "$dest_path/$name"
Complete script:
dest_path=/home/all/todo
line="name"
mkdir_for_name() {
echo "$1"
mkdir "$2"
}
mkdir_for_name "$name" "$dest_path/$name"
Your function uses $2, but you're only calling it with one argument, so $2 is empty.
You defined a function that accepts 2 arguments, where the first argument passed is the name to be printed on screen (the "echo" line), while the second argument passed will create the desidered folder.
Passing only one argument will just print on screen that argument

Passing and return value of external function in awk

I am calling function from another script from awk.
Why i need to press enter even after adding /dev/null
Why the passed argument is not displayed. I am getting spaces.
I am not getting the return value from external function.
cat mainpgm.sh
#!/bin/bash
key="09"
awk -v dk="$key" ' { ma = system(". /home/ott/functions.sh;derived dk")</dev/null ; "print returned value" ma } '
cat functions.sh
#!/bin/bash
derived () {
echo "outside function" $dk
return 9
}
If you don't want to process input in awk, redirect its input to /dev/null, and do everything in the BEGIN block. Also, for the dk variable to be replaced with its value, it has to be outside the quotes.
awk -v dk="$key" 'BEGIN {
ma = system(". /home/ott/functions.sh;derived " dk);
print "returned value", ma
}' < /dev/null
To answer your questions:
You put /dev/null in the wrong place. It's supposed to be the input of the script, not the system function.
Two reasons: First, you put dk inside the quotes, so its value is not substituted. Second, the derived function doesn't print its argument, it prints $dk, which is a nonexistent shell variable. The argument to a function is $1, so it should do:
echo "outside function $1"
You had print inside the quotes, so it wasn't being executed as a statement.

Shell Script for Searching text with variable and replace it with content

im new to shell script, but i need something to search a file with any given variable, and if the file contains this variable replace it with the variables alias
the text would be some thing like:
74304050 = +4574304050#voip1.local
74304051 = +4574304051#voip1.local
20304050 = +4520304050#voip2.local
20304051 = +4520304051#voip2.local
so if i use call the shell script with 20304050 i get +4520304050#voip1.local
how can this be done, i need it for calling aliases and rewriting them in opensips config file?
It's a bit underspecified, but does this do what you want?
awk -V number=20304050 '$1 == $number { print $3 }' file

mutiple returns from a function in a shell script

function get_arguments()
{
read -p 'data : ' data
read -p 'lambda: ' lambda
echo $data $lambda
}
data,lambda=$(get_arguments)
But i am getting an error
data : /home/wolfman/Downloads/data
lambda value: 2
./shell_script.sh: line 25: data,lambda,= /home/wolfman/Downloads/data: No such file or directory
But
1) Why is it even evaluating that whether that file exists or not.. its just a string??
2) what am i doing wrong :(
THanks
sh syntax does not allow that. But, the variables in the function are global, so you can just invoke the function and data and lambda will be set in the caller.
functions return an integer value, but they can print arbitrary data which can be read by the caller. For example, you could do:
get_arguments | { read data lambda; echo $data $lambda; }
The drawback is that the values are only available in that block. (The pipe creates a subshell, and the values read by read are only valid in that subshell.)
Just for fun here are a couple of other possible methods.
read -r data lambda <<< $(get_arguments)
or
set -- $(get_arguments)
data=$1
lambda=$2
shells don't allow direct assignment to lists of variables, you have manage that with shell string parsing (or possibly other methods). Try
data_lambda=$(get_arguments)
data=${data_lambda% *}
#-----------------^^space char
lambda=${data_lambda#* }
#------------------^^space char
$d=123 l=345
$data_lambda=$(echo $d $l)
$echo $data_lambda
123 345
$data=${data_lambda% *}
$lambda=${data_lambda#* }
$echo $data
123
$echo $lambda
345
Substituting $(echo $d $l) for data_lambda=$(get_arguments)`.
See my write-up on shell parameter modifiers
IHTH

Resources