How to give a text file into a shell function? - bash

Hi I'm trying to make a function which should get a text file and then do some things on it and then echo. But when I try to execute it, it says syntax error near unexpected token `"$cat"'
#!/bin/usr/bash
cat=$(< cat_dialogue.txt)
function test_cat (){
echo $1
}
test_cat($cat)
desired output:
>meow meow

Your program may look like the following. Note all differences. Check your scripts with shellcheck.
#!/usr/bin/env bash
cat=$(< cat_dialogue.txt)
test_cat() {
echo "$1"
}
test_cat "$cat"

Here is an example BASH function that strips a branchname:
#create function
function strip () {
#create local variable that takes input and fills $TEXT
local TEXT=$1
#stips the branch number from the branchname
echo $TEXT | sed 's/-[0-9]*//2'
}
strip "testbranch-12345-28796"
hope it helps :) also check the BASH documentation as mentioned by #joshmeranda

Related

eval cat inside a function

I've been trying to evaulate an expression inside a function as follows:
eval "fn() { $(cat fn.sh); }"
Where fn.sh contains the following:
#!/bin/sh
echo "You provided $1."
So that when I call:
fn "a phrase"`
it prints "You provided a phrase.". However I cannot get it to work.
What's particularly frustrating is that:
eval "$(cat fn.sh)"
works perfectly! What am I missing here?
What I've tried:
eval "fn() { \"\$(cat fn.sh)\"; }"
fn
# bash: #!/bin/sh
# echo "You provided $1."
# return 1: No such file or directory
eval "fn() { \$(cat fn.sh); }"
fn
# bash: #!/bin/sh: No such file or directory
and myriad other combinations, most of which at this point is guess work.
Found the answer:
eval "fn() { eval \"\$(cat "fn.sh")\"; }"
Mandatory reference that explains to the best degree I understand the security risks of using eval.
Just use source/. from inside the new function.
fn () {
. fn.sh "$1"
}
If the function is used often enough where you think repeated disk I/O would be an issue, the file will almost certainly be in a disk cache when you call fn.

Random command not found error in shell script [duplicate]

Hi gusy I am trying to learn Bash and cannot seem to get this basic script to work.
#!/bin/bash
function system_info
{
echo "function system_info"
}
$(system_info)
I get a function: command not found issue.
Bash is trying to evaluate the string that is outputted by the system_info function. You'll want to try the following, which will just simply run the function:
system_info
or to store the outputted value to a variable:
value=$(system_info)
You need to invoke the function by saying:
system_info
$(...) is used for command substitution.
Invoke the function inside the script with just the function name and execute the script from the shell
#!/bin/bash
function system_info {
echo "function system_info"
}
system_info
#!/bin/bash
function system_info
{
echo "function system_info"
}
echo $(system_info)
Kind of redundant but it works without the command not found error.
Or This:
#!/bin/bash
function system_info
{
echo "function\n system_info"
}
printf "$(system_info)"
If you want to use newline character.
You can try this code in: https://www.tutorialspoint.com/execute_bash_online.php

Get bash function path from name

A hitchhiker, waned by the time a function is taking to complete, wishes to find where a function is located, so that he can observe the function for himself by editting the file location. He does not wish to print the function body to the shell, simply get the path of the script file containing the function. Our hitchhiker only knows the name of his function, which is answer_life.
Imagine he has a function within a file universal-questions.sh, defined like this, the path of which is not known to our hitchhiker:
function answer_life() {
sleep $(date --date='7500000 years' +%s)
echo "42"
}
Another script, called hitchhiker-helper-scripts.sh, is defined below. It has the function above source'd within it (the hitchhiker doesn't understand source either, I guess. Just play ball.):
source "/usr/bin/universal-questions.sh"
function find_life_answer_script() {
# Print the path of the script containing `answer_life`
somecommand "answer_life" # Should output the path of the script containing the function.
}
So this, my intrepid scripter, is where you come in. Can you replace the comment with code in find_life_answer_script that allows our hitchhiker to find where the function is located?
In bash operating in extended debug mode, declare -F will give you the function name, line number, and path (as sourced):
function find_life_answer_script() {
( shopt -s extdebug; declare -F answer_life )
}
Like:
$ find_life_answer_script
answer_life 3 ./universal-questions.sh
Running a sub-shell lets you set extdebug mode without affecting any prior settings.
Your hitchhiker can also try to find the answer this way:
script=$(readlink -f "$0")
sources=$(grep -oP 'source\s+\K[\w\/\.]+' $script)
for s in "${sources[#]}"
do
matches=$(grep 'function\s+answer_life' $s)
if [ -n "${matches[0]}" ]; then
echo "$s: Nothing is here ("
else
echo "$s: Congrats! Here is your answer!"
fi
done
This is for case if debug mode will be unavailable on some planet )

Are there any existing methods for importing functions from other scripts without sourcing the entire script?

I am working on a large shell program and need a way to import functions from other scripts as required without polluting the global scope with all the internal functions from that script.
UPDATE: However, those imported functions have internal dependancies. So the imported function must be executed in the context of its script.
I came up with this solution and wonder if there is any existing strategy out there and if not, perhaps this is a really bad idea?
PLEASE TAKE A LOOK AT THE POSTED SOLUTION BEFORE RESPONDING
example usage of my solution:
main.sh
import user get_name
import user set_name
echo "hello $(get_name)"
echo "Enter a new user name :"
while true; do
read user_input < /dev/tty
done
set_name $user_input
user.sh
import state
set_name () {
state save "user_name" "$1"
}
get_name () {
state get_value "user_name"
}
As one approach, you could put a comment in the script to indicate where you want to stop sourcing:
$ cat script
fn() { echo "You are running fn"; }
#STOP HERE
export var="Unwanted name space pollution"
And then, if you are using bash, source it like this:
source <(sed '/#STOP HERE/q' script)
<(...) is process substitution and our process, sed '/#STOP HERE/q' script just extracts the lines from script until the stop line is reached.
Adding more precise control
We can select particular sections from a file if we add both start and stop flags:
$ cat script
export var1="Unwanted name space pollution"
#START
fn1() { echo "You are running fn1"; }
#STOP
export var2="More unwanted name space pollution"
#START
fn2() { echo "You are running fn2"; }
#STOP
export var3="More unwanted name space pollution"
And then source the file like this:
source <(sed -n '/#START/,/#STOP/p' script)
create standalone shel script that do this
will have 2 argument the file name and the function name
it will source the input file first
it will then use declare -f function name
in your code you can include functions like this
eval "./importfunctions.sh filename functionaname"
what is happening here :
step 1 basically read the file and source it in new shell environment . then it will echo the function declaration
step 2 will eval that function into our main code
So final result is as if we wrote just that function in our main script
When the functions in the script indent untill the closing } and all start with the keyword function, you can include specific functions without changing the original files:
largeshell.sh
#!/bin/bash
function demo1 {
echo "d1"
}
function demo2 {
echo "d2"
}
function demo3 {
echo "d3"
}
function demo4 {
echo "d4"
}
echo "Main code of largeshell... "
demo2
Now show how to source demo1() and forget demo4():
source <(sed -n '/^function demo1 /,/^}/p' largeshell.sh)
source <(sed -n '/^function demo3 /,/^}/p' largeshell.sh)
demo1
demo4
Or source all functions in a loop:
for f in demo1 demo3; do
echo sourcing $f
source <(sed -n '/^function '$f' /,/^}/p' largeshell.sh)
done
demo1
demo4
You can make it more fancy when you source a special script that will:
grep all strings starting with largeshell., like largefile.demo1
generate functions like largefile.demo1 that will call demo1
and source all functions that are called.
Your new script will look like
source function_includer.sh
largeshell.demo1
largeshell.demo4
EDIT:
You might want to reconsider your requirements.
Above solution is not only slow, but it will also make it hard for the
guys and ladies who made tha largeshell.sh. As soon as they are going to refactor their code or replace it with something in another language,
they have to refactor, test and deploy your code as well.
A better path is extracting the functions from largeshell.sh into some smaller files ("modules"), and put them in a shared directory (shlib?).
With names as sqlutil.sh, datetime.sh, formatting.sh, mailstuff.sh and comm.sh you can pick the includes file you need (and largefile.sh will include them all).
It's been a while and it would appear that my original solution is the best one out there. Thanks for the feedback.

AIX - bash script

I'm trying to implement a small bash script in AIX, but I'm having some problems. Bellow you can find a example. I have another question, if I want to add the script to Crontab, I think I'll have problems to call serverStatus.sh from IBM, how can avoid this problem.
#!/usr/bin/sh
WAS_HOME="/usr/IBM/WebSphere/AppServer/profiles/bpmnprd01/"
function StatusCheck()
{
$WAS_HOME/bin/serverStatus.sh BPM.AppTarget.bpmnprd01.0 -username admin -password admin
status=$(cat /usr/IBM/WebSphere/AppServer/profiles/bpmnprd01/logs/BPM.AppTarget.xxxxx/serverStatus.log| awk '{ if (NF > 0) { last = $NF } } END { print last }' "$#")
text="STOPPED"
if [[ $text == $status ]]
then
echo "OK"
else
echo "NOK"
fi
}
function start()
{
StatusCheck
}
start
-----------------------
when I try to execute the script above, I get the following error:
[root#bpmnprd01]/root/health_check# ./servers_check.sh
./servers_check.sh[7]: 0403-057 Syntax error at line 7 : `(' is not expected.
...after this I search on google, and I found some examples without "()" on subroutine.But I got this:
[root#bpmnprd01]/root/health_check# ./servers_check.sh
./servers_check.sh[30]: 0403-057 Syntax error at line 33 : `StatusCheck' is not expected.
Thanks in Advance
Tiago
AIX has a true bourne shell living in /bin/sh, not sure about /usr/bin/sh, but would expect that to be Bourne shell as well.
Change your script heading line (the #shebang!) to
#!/usr/bin/bash
Or the result of which bash
IHTH
You are using bash specific syntax but calling the script with sh, which has more limited capabilities. Since you want to use sh, you can use a tool like checkbashisms or shellcheck to help uncover non-portable syntax.
The immediate problem is that function foo() { ..; } is not a POSIX compliant function definition, and you should drop the keyword function and use just foo() { ..; }.
Your shell may also be lacking [[ ]] in which case you should use [ ] instead, with = instead of ==.

Resources