sh script syntax in linux

sh script syntax in linux

Everyone who plays linux knows the convenience of sh scripts, but how to write sh scripts is a difficult problem for newbies and novices like me. It is one thing to be able to write it, and another to understand it. With the spirit of studying hard and improving every day, everyone can take a look when you have time, there is no harm. Let's copy a large section of the syntax of the sh script. Take your time:

1. Beginning
The program must start with the following line (must be in the first line of the file):
#!/bin/sh
The symbol #! is used to tell the system that the parameters behind it are the program used to execute the file. In this example we use /bin/sh to execute the program.
When the scripting is complete, if the script is to be executed, it must also be made executable.
To make the script executable:
compile chmod +x filename so that it can be run with ./filename

2. Comments
In shell programming, sentences beginning with # represent comments until the end of this line.

3. Variables
In shell programming, all variables are composed of strings, and there is no need to declare variables. To assign a value to a variable, write:
#!/bin/sh #Assign
the variable:
a=”hello world”
# Now print the contents of variable a:
echo “A is:”
echo $a
Sometimes variable names are easy Confused with other literals like:
num=2
echo "this is the $numnd"
This doesn't print "this is the 2nd", it just prints "this is the" because the shell searches for the value of the variable numnd, But this variable has no value. We can use curly braces to tell the shell that we want to print the num variable:
num=2
echo "this is the ${num}nd"
This will print: this is the 2nd

Fourth, environment variables Variables
processed by the export keyword are called environment variables. We do not discuss environment variables because they are typically only used in login scripts.

5. Shell commands and process control
Three types of commands can be used in shell scripts:
1) Unix commands:
Although any unix commands can be used in shell scripts, there are still some relatively more commonly used commands. These commands are usually used for file and text operations.
Common command syntax and functions
echo “some text”: print the text content on the screen
ls: file list
wc –l filewc -w filewc -c file: Count the number of lines in the file Count the number of words in the file Count the number of characters in the file
cp sourcefile destfile: file copy
mv oldname newname : rename file or move file
rm file: delete file
grep 'pattern' file: search string in file for example: grep 'searchstring' file.txt
cut -b colnum file: specify to display range of file contents and output them to the standard output device. For example: output the 5th to 9th characters of each line cut -b5-9 file.txt Do not confuse with the cat command, these are two completely different commands
cat file.txt: output the contents of the file to the standard output device (screen)
file somefile: get the file type
read var: prompt the user for input and assign the input to the variable
sort file.txt: sort the lines in the file.txt file
uniq: delete lines and columns appearing in a text file e.g. sort file.txt | uniq
expr: perform mathematical operations Example: add 2 and 3expr 2 “+” 3
find: search for files e.g. find by filename . -name filename -print
tee: output data to stdout (screen) and files e.g. somecommand | tee outfile
basename file: Returns the file name without the path. For example: basename /bin/tux will return tux
dirname file: Returns the path where the file is located. For example: dirname /bin/tux will return /bin
head file: Print the first few lines of the text file
tail file : print the last few lines of a text file
sed: Sed is a basic find and replace program. You can read text from standard input (such as a command pipe) and output the results to standard output (the screen). This command uses regular expressions (see Reference) to search. Not to be confused with wildcards in the shell. For example: replace linuxfocus with LinuxFocus: cat text.file | sed 's/linuxfocus/LinuxFocus/' >newtext.file
awk: awk is used to extract fields from text files. By default, the field delimiter is a space, other delimiters can be specified with -F.
catfile.txt | awk -F, '{print $1 "," $3}' Here we use "," as the field separator and print the first and third fields at the same time. If the content of the file is as follows: Adam Bor, 34, IndiaKerryMiller, 22, USA The command output is: Adam Bor, IndiaKerry Miller, USA

2) Concept: pipes, redirects and backtick
are not system commands, but they are really important.
1. Pipeline (|)—The output of one command is used as the input of another command.
grep "hello" file.txt | wc -l
searches file.txt for lines containing "hello" and counts the number of lines.
Here the output of the grep command is used as the input of the wc command. Of course you can use multiple commands.
2. Redirection - Output the result of the command to a file instead of standard output (screen).
3.>—– write the file and overwrite the old file
4.>>—– add to the end of the file, keep the old file content.
5. Backslashes - Use backslashes to pass the output of one command as a command-line argument to another command.
Command:
find . -mtime -1 -type f -print
is used to find files modified in the past 24 hours (-mtime -2 means the past 48 hours). If you want to pack all the files found, you can use the following linux script:
#!/bin/sh
# The ticks are backticks (`) not normal quotes ('):
tar -zcvf lastmod.tar.gz ` find . -mtime -1 -type f -print`

3) Flow control
1.if
"if" expression if the condition is true then execute the part after then:
if ….; then
….
elif ….; then
….
else
….
fi
In most cases, the test command can be used to test the conditions. For example, you can compare strings, determine whether the file exists and whether it is readable, etc...

Usually " [ ] " is used to denote conditional tests. Note that spaces are important here. Be sure to space the square brackets.
[ -f "somefile" ] : determine whether it is a file
[ -x "/bin/ls" ] : determine whether /bin/ls exists and has executable permissions
[ -n "$var" ] : determine whether the $var variable Has value
[ "$a" = "$b" ]: Determine whether $a and $b are equal.
Execute man test to view the types that can be compared and judged by all test expressions.
Execute the following script directly:
#!/bin/sh
if [ “$SHELL” = “/bin/bash” ]; then
echo “your login shell is the bash (bourne again shell)”
else
echo “your login shell is not bash but $SHELL"
fi
variable $SHELL contains the name of the login shell, which we compared to /bin/bash.
Shortcut Operators
Friends who are familiar with C language may like the following expressions:
[ -f “/etc/shadow” ] && echo “This computer uses shadow passwors”
where && is a shortcut operator, if the expression on the left is True executes the statement on the right.
You can also think of it as the AND operation in logical operations. The above example means that "This computer uses shadow passwors" is printed if the /etc/shadow file exists. The same OR operation (||) is also available in shell programming. Here's an example:
#!/bin/sh
mailfolder=/var/spool/mail/james
[ -r "$mailfolder" ]' '{ echo "Can not read $mailfolder" ; exit 1; }
echo "$mailfolder has mail from:"
grep "^From " $mailfolder
The script first checks whether the mailfolder is readable. Prints the "From" line in the file if it is readable. If it is not readable or the operation is valid, the script exits after printing an error message. The problem here is that we have to have two commands:
◆ print an error message
◆ exit the program
We use curly braces to put the two commands together as a single command in the form of an anonymous function. The general functions will be mentioned below.
We can do anything with if expressions without the AND and OR operator, but it is much more convenient to use the AND OR operator.

2.case
case: Expressions can be used to match a given string, not a number.
case … in
…) do something here ;;
esac
Let's look at an example. The file command can identify the file type of a given file, for example:
file lf.gz
This will return:
lf.gz: gzip compressed data, deflated, original filename,
last modified: Mon Aug 27 23:09:18 2001, os : Unix
We took advantage of this by writing a script called smartzip that automatically decompresses bzip2, gzip and zip type compressed files:
#!/bin/sh
ftype=`file “$1″`
case “$ftype” in
“ $1: Zip archive”*)
unzip “$1” ;;
“$1: gzip compressed”*)
gunzip “$1” ;;
“$1: bzip2 compressed”*)
bunzip2 “$1” ;;
*) echo “File $1 can not be uncompressed with smartzip";;
esac
You may notice that we use a special variable $1 here. This variable contains the value of the first parameter passed to the program.
That is, when we run:
smartzip articles.zip
$1 is the string articles.zip

3. The
select select expression is an extended application of bash, especially good at interactive use. The user can choose from a different set of values.
select var in … ; do
break
done
…. now $var can be used ….
Here is an example:

#!/bin/sh
echo “What is your favourite OS?”
select var in “Linux” “Gnu Hurd” “Free BSD” “Other”; do
break
done
echo “You have selected $var”
下面是该脚本运行的结果:
What is your favourite OS?
1) Linux
2) Gnu Hurd
3) Free BSD
4) Other
#? 1
You have selected Linux

4.loop
while-loop will run until the expression tests true. will run while the expression that we test for is true.
The keyword "break" is used to break out of the loop. The keyword "continue" is used to skip to the next loop without executing the rest.
while …; do
….
done

The for-loop expression looks at a list of strings (strings separated by spaces) and assigns it to a variable:
for var in ....; do
....
done
In the following example, ABC will be printed to the screen respectively:
# !/bin/sh
for var in ABC ; do
echo “var is $var”
done
Here is a more useful script showrpm that prints some RPM package statistics:
#!/bin/sh
# list a content summary of a number of RPM packages
# USAGE: showrpm rpmfile1 rpmfile2 …
# EXAMPLE: showrpm /cdrom/RedHat/RPMS/*.rpm
for rpmpackage in $*; do
if [ -r “$rpmpackage” ];then
echo “== ============= $rpmpackage =============”
rpm -qi -p $rpmpackage
else
echo “ERROR: cannot read file $rpmpackage”
fi
done
A second special variable, $*, appears here, which contains all the entered command-line parameter values.
If you run showrpm openssh.rpm w3m.rpm webgrep.rpm then
$* contains 3 strings, namely openssh.rpm, w3m.rpm and webgrep.rpm.

5. Quotes
The program expands wildcards and variables before passing any arguments to the program. The so-called expansion here means that the program will replace the wildcard (such as *) with the appropriate file name, and it will replace the variable with the variable value. To prevent the program from making this substitution, you can use quotation marks: let's look at an example, suppose there are some files in the current directory, two jpg files, mail.jpg and tux.jpg.

1.2 Compile the SHELL script
#ch#!/bin/sh mod +x filename
cho *.jpg ∪ Slow   Shao Yun ü  巙 脄?./filename to execute your script. 【? ? ? ]
This will print out the result of "mail.jpg tux.jpg".
Quotes (single and double) will prevent this wildcard expansion:
#!/bin/sh
echo "*.jpg"
echo '*.jpg'
This will print "*.jpg" twice.
Single quotes are more restrictive. It prevents any variable expansion. Double quotes prevent wildcard expansion but allow variable expansion.
#!/bin/sh
echo $SHELL
echo "$SHELL"
echo '$SHELL'
results in:
/bin/bash
/bin/bash
$SHELL
Finally, there is another way to prevent this expansion, which is to use escape character - backslash:
echo *.jpg
echo $SHELL
This will output:
*.jpg
$SHELL

6. Here documents Here documents
are a good way to pass several lines of text to a command. It's useful to write a helpful text for each script, so if we have the here documents we don't have to use the echo function to output line by line. A "Here document" with shift by 2
–) shift;break;; # end of options
-*) echo “error: no such option $1. -h for help”;exit 1;;
*) break;;
esac
done
echo "opt_f is $opt_f"
echo "opt_l is $opt_l"
echo "first arg is $1"
echo "2nd arg is $2"
You can run the script like this:
cmdparser -l hello -f -- -somefile1 somefile2
returns:
opt_f is 1
opt_l is hello
first arg is -somefile1
2nd arg is somefile2
How does this script work? The script first loops through all the input command line arguments, compares the input arguments to the case expression, sets a variable and removes the argument if it matches. According to the convention of unix systems, the first input should be the parameter containing the minus sign.

Part 2 Examples
Now let's discuss the general steps for writing a script. Any good script should have help and input parameters. And it's a very good idea to write a pseudo script (framework.sh) that contains the framework structure that most scripts need. At this time, when writing a new script, we only need to execute the copy command:
cp framework.sh myscript
and then insert our own function.
Let's look at two more examples:
Binary to Decimal Conversion The
script b2d converts a binary number (eg 1101) to the corresponding decimal number. This is also an example of doing math with the expr command:
#!/bin/sh
# vim: set sw=4 ts=4 et:
help()
{
cat <
b2h — convert binary to decimal
USAGE: b2h [-h] binarynum
OPTIONS: -h help text
EXAMPLE: b2h 111010
will return 58
HELP
exit 0
}
error()
{
# print an error and exit
echo “$1”
exit 1
}
lastchar()
{
# return the last character of a string in $rval
if [ -z “$1″ ]; then
# empty string
rval=””
return
fi
# wc puts some space behind the output this is why we need sed:
numofchar=`echo -n “$1” | wc -c | sed ‘s/ //g’ `
# now cut out the last char
rval=`echo -n “$1” | cut -b $numofchar`
}
chop()
{
# remove the last character in string and return it in $rval
if [ -z “$1″ ]; then
# empty string
rval=””
return
fi
# wc puts some space behind the output this is why we need sed:
numofchar=`echo -n “$1” | wc -c | sed ‘s/ //g’ `
if [ “$numofchar” = “1” ]; then
# only one char in string
rval=””
return
fi
numofcharminus1=`expr $numofchar “-” 1`
# now cut all but the last char:
rval=`echo -n “$1” | cut -b 0-${numofcharminus1}`
}
while [ -n “$1” ]; do
case $1 in
-h) help;shift 1;; # function help is called
–) shift;break;; # end of options
-*) error “error: no such option $1. -h for help”;;
*) break;;
esac
done
# The main program
sum=0
weight=1
# one arg must be given:
[ -z “$1″ ] && help
binnum=”$1″
binnumorig=”$1”
while [ -n “$binnum” ]; do
lastchar “$binnum”
if [ “$rval” = “1” ]; then
sum=`expr “$weight” “+” “$sum”`
fi
# remove the last position in $binnum
chop “$binnum”
binnum=”$rval”
weight =`expr "$weight" "*" 2`
done
echo "binary $binnumorig is decimal $sum"
The algorithm used by this script is to use decimal and binary weights (1,2,4,8,16,..) , for example binary "10" can be converted to decimal like this:
0 * 1 + 1 * 2 = 2
To get a single binary number we use the lastchar function. This function uses wc -c to count the number of characters, and then uses the cut command to remove the last character. The function of the Chop function is to remove the last character.

File Recycler
Maybe you're one of those people who wants to save all outgoing mail to a file, but after a few months the file can get so big that accessing the file is slow slow down. The following script rotatefile can solve this problem. This script renames the mail save file (let's say outmail) to outmail.1, which becomes outmail.2 for outmail.1 etc etc...

#!/bin/sh
# vim: set sw=4 ts=4 et:
ver=”0.1″
help()
{
cat <
rotatefile — rotate the file name
USAGE: rotatefile [-h] filename
OPTIONS: -h help text
EXAMPLE: rotatefile out
This will e.g rename out.2 to out.3, out.1 to out.2, out to out.1
and create an empty out-file
The max number is 10
version $ver
HELP
exit 0
}
error()
{
echo “$1”
exit 1
}
while [ -n “$1” ]; do
case $1 in
-h) help;shift 1;;
–) break;;
-*) echo “error: no such option $1. -h for help”;exit 1;;
*) break;;
esac
done
# input check:
if [ -z “$1” ] ; then
error “ERROR: you must specify a file, use -h for help”
fi
filen=”$1″
# rename any .1 , .2 etc file:
for n in 9 8 7 6 5 4 3 2 1; do
if [ -f “$filen.$n” ]; then
p=`expr $n + 1`
echo “mv $filen.$n $filen.$p”
mv $filen.$n $filen.$p
fi
done
# rename the original file:
if [ -f “$filen” ]; then
echo “mv $filen $filen.1”
mv $filen $filen.1
fi
echo touch $ How does the script filen
touch $filen
work? After detecting that the user provided a filename, we perform a 9-to-1 loop. File 9 is named 10, file 8 is renamed 9, and so on. After the loop is complete, we name the original file as file 1 and create an empty file with the same name as the original file.
debugging
The simplest debugging command is of course the echo command. You can use echo to print any variable value wherever you suspect something went wrong. This is why the vast majority of shell programmers spend 80% of their time debugging programs. The nice thing about shell programs is that they don't need to be recompiled, and it doesn't take much time to insert an echo command.
The shell also has a true debug mode. If there is an error in the script "strangescript", you can debug it like this:
sh -x strangescript
This will execute the script and display the values ​​of all variables.
The shell also has a mode that doesn't require executing scripts but just checks syntax. It can be used like this:
sh -n your_script
This will return all syntax errors.

Related logs

 
 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326129058&siteId=291194637