I have a script file written in Bash. what I'm trying to do is locate all the arguments used in the script ($1,$2,$3....)
I've tried using:
grep -o '$[0-9]' $1
but that gives me seperate digits. for example, if I have $54 somewhere in the script,
I will only get $5. how can I get the whole number?
You can use quantifier + to grab one or more digits:
grep -o '$[0-9]\+' "$1"
Related
I have a Makefile in which I have a text file and a certain number. I would like to compare the number of lines in that text file to see if it is equal to or greater than that number, but haven't had success using the wc bash command.
I've tried using wc on the text file, but $(wc -l < filename.txt) always evaluates as empty, making ifeq($(wc -l < filename.txt), number)) error out. I've tried using the bash syntax for if statements, but that didn't work either.
e.g.
TEST="$(wc -l < missing_test_line_count.txt)"
TEST1=$(wc -l missing_test_line_count.txt)
TEST2=`wc -l missing_test_line_count.txt`
TEST3="$(wc -l missing_test_line_count.txt)"
Doing #echo $(value TEST) for any of these variables (TEST thru TEST3) results in an empty output.
I've also tried to put the number of lines in the text file into another text file (e.g. linecount.txt with a single line that says '30'). Then I tried to get that file content stored into a variable so I could compare it to the number, but that hasn't worked because I cannot define the variable at the beginning.
Any suggestions? Is this possible, or do I have to write a script separately? Would like to do it within the Makefile if possible.
First of all, you should specify, that you need GNU make's syntax (your reference to ifeq is one's only clue to that).
Back to your actual question, there is no wc function in gmake itself. What you're trying to do is to execute an external command. You do that with a shell function:
TEST= $(shell wc -l < missing_test_line_count.txt)
In BSD make's the same is achieved with the !=-assignment:
TEST!= wc -l < missing_test_line_count.txt
To run a shell as part of a variable expansion in a GNUMakefile, you need to use the shell function:
TEST:=$(shell wc -l < missing_test_line_count.txt)
will run the command in question when this line is read in the Makefile, setting TEST to be the result. Alternately you can use
TEST=$(shell wc -l < missing_test_line_count.txt)
which will run the command each time the $(TEST) variable is expanded.
Note that this function (and functions in general) is a GNUMake extension. Normal make does not support doing this.
I have a directory "Main Dir" and I want to write a script, which will get 2 parameters: sorted_by_date , that will find in the directory the id-worker directory (it does exist) and in it, from a file called "sent.txt", it will print results-num (an integer) strokes sorted by date.
I'm a begginer in bash (have knowledge and skills mainly in C), and I stil didn't saw how to write scripts, but I've tried to do something from a little commands I learned and from a little search in the internet.
Can somebody help a newbie like me in my first script-writing ?
I'll paste here my first try:
#!/bin/bash
id_worker = "$1"
results_num = "$2"
sort -k3 -t "./Main Dir/id_worker/sent.text"
head -n+3 $results_num
I'm going to go out on a limb here, and assume your sort command is producing the information you want from the id_worker sent.txt file and that you are talking about the number of lines you want when you say strokes. Given the extended discussion in the comments, that is about the only thing I see that makes sense.
With that in mind, you were not that far off in your first attempt. What you needed to do to fix the sort command was to dereference your id_worker with $ to get the value you passed. In bash you assign variables as id_worker="something", but to get the value back, you must precede the variable with a $, just as you see with your id_worker="$1". NOTE: there are NO spaces allowed on either side of the '=' sign in bash. Putting that together, it looks like you intended:
sort -k3 -t "./Main Dir/$id_worker/sent.text"
Where you are beginning in the directory above Main Dir running your script because you have given a relative path "./Main Dir/stuff".
Now if you want to limit the number of lines to the first results_num lines of the sorted output, then you can use head, but you need to remove the "+" sign (which is only relevant with the tail command). To use it with the sorted output, you mustpipe the results of sort to head using the '|' pipe character. For example:
sort -k3 -t "./Main Dir/$id_worker/sent.text" | head -n $results_num
Putting all of the pieces that I think you intended, and including a short check to make sure both id_worker and results_num are given on the command line, you would end up with something like:
#!/bin/bash
## verify both arguments given
[ -z $1 -o -z $2 ] && {
printf "error: insufficient input. usage: %s worker num\n" "${0##*/}"
exit 1
}
id_worker="$1"
results_num="$2"
## pipe the results of sort to head to print first $results_num lines
sort -k3 -t "./Main Dir/$id_worker/sent.text" | head -n $results_num
Note: if you are having trouble with your script, run it with:
bash -x scriptname id_worker results_num
to enable line-by-line debugging output from bash. Let me know if I have not understood what you were saying or if the results are not what you intended. There are several ways of approaching this problem, but I do need to clearly understand what you want to go further. Good luck.
I would like to get just the filename (with extension) of the output file I pass to my bash script:
a=$1
b=$(basename -- "$a")
echo $b #for debug
if [ "$b" == "test" ]; then
echo $b
fi
If i type in:
./test.sh /home/oscarchase/test.sh > /home/oscarchase/test.txt
I would like to get:
test.txt
in my output file but I get:
test.sh
How can I procede to parse this first argument to get the right name ?
Try this:
#!/bin/bash
output=$(readlink /proc/$$/fd/1)
echo "output is performed to \"$output\""
but please remember that this solution is system-dependent (particularly for Linux). I'm not sure that /proc filesystem has the same structure in e.g. FreeBSD and certainly this script won't work in bash for Windows.
Ahha, FreeBSD obsoleted procfs a while ago and now has a different facility called procstat. You may get an idea on how to extract the information you need from the following screenshot. I guess some awk-ing is required :)
Finding out the name of the file that is opened on file descriptor 1 (standard output) is not something you can do directly in bash; it depends on what operating system you are using. You can use lsof and awk to do this; it doesn't rely on the proc file system, and although the exact call may vary, this command worked for both Linux and Mac OS X, so it is at least somewhat portable.
output=$( lsof -p $$ -a -d 1 -F n | awk '/^n/ {print substr($1, 2)}' )
Some explanation:
-p $$ selects open files for the current process
-d 1 selects only file descriptor 1
-a is use to require both -p and -d apply (the default is to show all files that match either condition
-F n modifies the output so that you get one line per field, prefixed with an identifier character. With this, you'll get two lines: one beginning with p and indicating the process ID, and one beginning with `n indicating the file name of the file.
The awk command simply selects the line starting with n and outputs the first field minus the initial n.
I am trying to prepare a bash script for use with gnu parallel. The script should take a filename, store the prefix of the file name as a describer, and store the row count (wc -l) as a numeric variable. Both if these become variables to use in a perl script. The describer is working fine.
But my storage of the number of rows, or my use of ${mm} is not generating a numeric variable that the perl script recognises. Any corrections appreciated.
#!/bin/bash
# Get the filename and strip suffix
sample=$1
describer=$(echo ${sample} | sed 's/.sync//')
echo ${describer} # works fine
# Get the number of rows
mm=$(cat ${sample} | wc -l)
echo ${mm} # works fine but is this a numeric variable?
# run the script using the variables;
# the ${mm} is where the perl script says its not numeric
perl script.pl --input ${describer}.sync --output ${describer}.genepop --region ${describer}:1-${mm}
This not an answer. I just wanted to rewrite your script in a better bash style. You know, you don't need to refer to variables with curly brackets all the time! E.g., $mm is fine enough, ${mm} is not needed in your cases. Moreover, your sed statement to strip the comment can be replaced with a bash equivalent. I added double quotes here and there so that you'll also be able to use everything with filenames that contain spaces and other funny symbols. I also removed the useless use of cat.
#!/bin/bash
# Get the filename and strip suffix
sample=$1
describer=${sample%.sync}
echo "$describer" # works fine
# Get the number of rows
mm=$(wc -l < "$sample")
echo "$mm" # works fine but is this a numeric variable?
# run the script using the variables;
# the $mm is where the perl script says its not numeric
perl script.pl --input "$sample" --output "$describer.genepop" --region "$describer:1-$mm"
Regarding your main problem: the problem might be in the perl program.
Regarding your question is this a numeric variable?, the answer is: variables have no types. They all are strings. Now read on:
Some versions of wc add spaces in front of the number they output, e.g.,
$ wc -l < file
42
(notice the spaces in front of 42). You should be able to notice if your version of wc behaves that way by running the version of the script I gave you (with the proper quotings). If you see some spaces in front of the number, that might be the cause of your problems.
If this is the case, you should replace the line
mm=$(wc -l < "$sample")
with
read mm < <(wc -l < "$sample")
Hope this helps!
I have a scala process command like below to use linux bash egrep command. But the search results are not the same in terminal and in my scala generated file. Scala results contain everything that has "new" and "Exception" while I want the output to contains only lines having "new Exception". Am I missing something here? Please help
if (("egrep -r -I -n -E \"*new Exception*\" /mysource/" #|
"grep -v .svn").! == 0) {
out.println(("egrep -r -I -n -E \"*new Exception*\" /mysource/" #|
"grep -v .svn").!!)
}
The docs say (under "What to Run and How"): Implicitly, each process is created either out of a String, with arguments separated by spaces -- no escaping of spaces is possible -- or out of a scala.collection.Seq, where the first element represents the command name, and the remaining elements are arguments to it. In this latter case, arguments may contain spaces
So, apparently if you need to pass the command line a single argument with spaces, like new Exception, you need to create the process builder from a Seq instead of a single String.