shell
# shell
Owner: -QVQ-
第一行需要指定解释器
#!/bin/bash
echo "Hello World !"
2
解释器种类
- Bourne Shell(/usr/bin/sh或/bin/sh)
- Bourne Again Shell(/bin/bash)
- C Shell(/usr/bin/csh)
- K Shell(/usr/bin/ksh)
- Shell for Root(/sbin/sh)
# 基础
# 变量
变量名和等号之间没有空格
定义:your_name="[runoob.com](http://runoob.com/)"
使用:$your_name
也可以 ${your_name}
区分echo "I am good at $skillScript”
和**echo** "I am good at ${skill}Script"
隐式赋值:for file in $(ls /etc)
将/etc下的目录的文件名循环出来
设置为只读变量:readonly variable_name
此时myUrl不能修改
删除变量:unset variable_name
不能删只读变量
字符串:
单引号:其中的变量无效,所有值原样输出。不能出现单个单引号(转义也不行),可以成对出现
双引号:可以有变量和转义字符
获取字符串长度:echo ${#variable_name}
提取子字符串:
string="runoob is a great site"
**echo** ${string:1:4} *# 输出 unoo*
# 数组
仅支持一维数组
数组名=(值1 值2 ... 值n)
array_name=(
value0
value1
)
array_name[100] = 10
echo ${array_name[100]}
2
3
4
5
6
可以不使用连续的下标,下标范围没有限制
获取数组的所有元素:echo ${array_name[@]}
获取数组长度
# 取得数组元素的个数
length=${#array_name[@]}
# 或者
length=${#array_name[*]}
# 取得数组单个元素的长度
length=${#array_name[n]}
2
3
4
5
6
# 关联数组
declare -A array_name
declare -A site=(["google"]="[www.google.com](http://www.google.com/)" ["runoob"]="[www.runoob.com](http://www.runoob.com/)")
declare -A site
site["google"]="www.google.com"
site["runoob"]="www.runoob.com"
# 访问
echo ${site["google"]}
# 输出值
echo "数组的元素为: ${my_array[*]}"
echo "数组的元素为: ${my_array[@]}" # 数组的元素为: www.google.com www.runoob.com
# 输出键
echo "数组的键为: ${!site[*]}"
echo "数组的键为: ${!site[@]}" # 数组的键为: google runoob
2
3
4
5
6
7
8
9
10
11
12
13
# 注释
#开头的均为注释
###########也是注释
对于代码的注释,可以把代码扩起来定义成函数,不调用从而达到注释的效果
多行注释
:*<<EOF #这个EOF是标识符可自定义为任何符号
注释内容...
注释内容...
注释内容...
EOF #两个标识符中间的会被视为注释
:<<'
注释内容...
注释内容...
注释内容...
'*
2
3
4
5
6
7
8
9
10
11
# 参数传递
对于脚本传入的参数 ./***.sh 参数1 参数2 参数3
用$1 $2 $3来接收
自带的一些参数
$0 | 表示当前脚本的名字 |
---|---|
$# | 传递到脚本的参数个数 |
$* | 以一个单字符串显示所有向脚本传递的参数。如"$*"用「"」括起来的情况、以"$1 $2 … $n"的形式输出所有参数。 |
$@ | 与$*相同, |
不同点只在双引号体现 “$*”为“1 2 3” “$@”为“1” “2” “3” | | $$ | 脚本运行的当前进程ID号 | | $! | 后台运行的最后一个进程的ID号 | | $- | 显示Shell使用的当前选项,与set命令 (opens new window)功能相同。 | | $? | 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。 |
# 输入输出
输入
read 变量名
等待用户输入内容到变量名里
read -p "输出信息" 变量名
输出信息并等待用户输入
输出
echo函数
echo It is a test
可以不加引号
# -e开启转义字符 不加上就会原样输出字符串
echo -e "ok ! \n ko" #/n换行
# ok
# ko
echo -e "hel /c" # /c 不换行
echo -e "lo"
# hello
echo `data` # `` 显示命令执行结果
# 输出当前的日期
2
3
4
5
6
7
8
9
10
11
printf函数
printf format-string [arguments...]
printf "%-10s %-8s %-4s\n" 姓名 性别 体重kg
printf "%-10s %-8s %-4.2f\n" 郭靖 男 66.1234
printf "%-10s %-8s %-4.2f\n" 杨过 男 48.6543
printf "%-10s %-8s %-4.2f\n" 郭芙 女 47.9876
:>>'
输出结果
姓名 性别 体重kg
郭靖 男 66.12
杨过 男 48.65
郭芙 女 47.99
'
2
3
4
5
6
7
8
9
10
11
%-10s 指一个宽度为 10 个字符(- 表示左对齐,没有则表示右对齐),超过内容会将内容全部显示出来
%-4.2f 指格式化为小数,其中 .2 指保留2位小数。
# 流程控制
# 条件判断
if 条件1
then
command1
command2
...
commandN
elif 条件2
then 执行2
else 执行3
fi
2
3
4
5
6
7
8
9
10
#!/bin/bash
if [ ! -d "build" ]; then # if后面,[后面,]前面都要加空格
mkdir build
fi
2
3
4
注意不能if里不能空语句,if里0代表true,0以外的值代表false
# test命令
检查某个条件是否成立,数值、字符和文件三个方面的测试
if test $[num1] -eq $[num2]
# 等同于使用[]
if [ $[num1] -eq $[num2] ]
2
3
# 基本运算符
查找子字符串:
string="runoob is a great site”
echo** **
expr index "$string" io****
# 输出 4
相当于在$string
里查找i和o,先找到那个返回哪个的下标
echo** **
expr index "$string" "si""bo"****
# 输出 4,因为o的下标是4
算术运算符
val=**expr** 2 + 2**
注意:**运算符两边要有空格
特别的 :乘号()前边必须加反斜杠()才能实现乘法运算val=**
expr** $a **** $b`
条件表达式
[ $a == $b ] 注意:[]和中间的值需要有空格
关系运算符
使用[……]格式的
-eq 相等 [$a -eq $b]
-ne 不等
-gt 大于
-lt 小于
-ge 大于等于
-le 小于等于
使用((……))格式的
可以直接使用> <号
布尔运算
!非 -o 或 -a 与
逻辑运算
&& ||
字符串运算符
[ $a = $b ] 检测字符串是否相等
[ $a != $b ] 检测字符串是否不等
[ -z $a ] 检测字符串长度是否为0
[ -n $a ] 检测字符串长度是否不为0
[ $a ] 检测字符串是否为空
文件测试运算符
操作符 | 说明 | 举例 |
---|---|---|
-b file | 检测文件是否是块设备文件,如果是,则返回 true。 | [ -b $file ] 返回 false。 |
-c file | 检测文件是否是字符设备文件,如果是,则返回 true。 | [ -c $file ] 返回 false。 |
-d file | 检测文件是否是目录,如果是,则返回 true。 | [ -d $file ] 返回 false。 |
-f file | 检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。 | [ -f $file ] 返回 true。 |
-g file | 检测文件是否设置了 SGID 位,如果是,则返回 true。 | [ -g $file ] 返回 false。 |
-k file | 检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。 | [ -k $file ] 返回 false。 |
-p file | 检测文件是否是有名管道,如果是,则返回 true。 | [ -p $file ] 返回 false。 |
-u file | 检测文件是否设置了 SUID 位,如果是,则返回 true。 | [ -u $file ] 返回 false。 |
-r file | 检测文件是否可读,如果是,则返回 true。 | [ -r $file ] 返回 true。 |
-w file | 检测文件是否可写,如果是,则返回 true。 | [ -w $file ] 返回 true。 |
-x file | 检测文件是否可执行,如果是,则返回 true。 | [ -x $file ] 返回 true。 |
-s file | 检测文件是否为空(文件大小是否大于0),不为空返回 true。 | [ -s $file ] 返回 true。 |
-e file | 检测文件(包括目录)是否存在,如果是,则返回 true。 | [ -e $file ] 返回 true。 |
-S | 判断文件是否socket | |
-L | 检测文件是否存在并是一个符号链接 |
/dev/null
一个特殊的文件,用于将数据彻底丢弃,可以帮助你消除干扰和减少资源占用
用途:重定向输出,可以禁止输出输入,使得不在屏幕上打出信息
/not/a/real/path > /dev/null
cat < /dev/null
2
2>&1
将错误的信息也重定向
./test.sh > log.txt 2>&1
将文件描述2(标准错误输出)的内容重定向到文件描述符1(标准输出),有&表示重定向的目标是一个文件描述符(而不是一个普通文件)
./test.sh>log.txt 将标准输出拷贝到log.txt,2>&1把标准错误输出拷贝到标准输出,即把标准错误输出拷贝到log.txt
# 循环语句
for语句
for var in item1 item2 ... itemN
do
command1
command2
...
commandN
done
for var in item1 item2 ... itemN; do command1; command2… done;
# 下面这种语法只在bash中支持
for((i=1;i<=5;i++));do
……;
done;
2
3
4
5
6
7
8
9
10
11
12
13
in列表包含替换、字符串、文件名
for loop in 1 2 3 4 5
do
echo "The value is: $loop"
done
2
3
4
for语句通过in读文件的数据,是以空格和制表符为分隔符的。可以通过设置IFS(内部字段分隔符)变量来更改默认分隔符。
while语句
while condition
do
command
done
2
3
4
int=1
while(( $int<=5 ))
do
echo $int
# let "int++" # 用于执行一个或多个表达式,变量计算不需要加$
int=$int+1
done
2
3
4
5
6
7
until语句
循环直到条件为真,和while语句相反
a=0
until [ ! $a -lt 10 ]
do
echo $a
a=`expr $a + 1`
done
2
3
4
5
6
case esac语句
case 值 in
模式1) # 每个分支用)表示开始
command1
command2
...
commandN
;; # 每个分支用;;表示break
模式2)
command1
command2
...
commandN
;;
*) # 如果没有匹配到的用*捕获该值,再执行后面的
command1
command2
...
commandN
;;
esac
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
case $aNum in
1) echo '你选择了 1'
;;
2) echo '你选择了 2'
;;
3) echo '你选择了 3'
;;
4|5|6) echo '你选择了 4或5或6'
;;
*) echo '你没有输入 1 到 4 之间的数字'
;;
esac
2
3
4
5
6
7
8
9
10
11
12
同样有break和continue
# 函数
[ function ] funname [()]
{
action;
[return int;] # 不加return将以最后一条命令运行结果作为返回值
# return后只能跟数字,范围是0-255
}
2
3
4
5
6
funWithParam(){
echo "第一个参数为 $1 !"
echo "第二个参数为 $2 !"
echo "第十个参数为 $10 !" # 超过了9就必须用{括起来}
echo "第十个参数为 ${10} !"
echo "第十一个参数为 ${11} !"
echo "参数总数有 $# 个!"
echo "作为一个字符串输出所有参数 $* !"
return $1
}
funWithParam 1 2 3 4 5 6 7 8 9 34 73
echo "$?" # $?只对上一条指令负责,函数返回值没有即使获得,将不能通过$?得到
:>>'
第一个参数为 1 !
第二个参数为 2 !
第十个参数为 10 !
第十个参数为 34 !
第十一个参数为 73 !
参数总数有 11 个!
作为一个字符串输出所有参数 1 2 3 4 5 6 7 8 9 34 73 !
'
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 输入输出重定向
命令 | 说明 |
---|---|
command > file | 将输出重定向到 file。 |
command < file | 将输入重定向到 file。 |
command >> file | 将输出以追加的方式重定向到 file。 |
n > file | 将文件描述符为 n 的文件重定向到 file。 |
n >> file | 将文件描述符为 n 的文件以追加的方式重定向到 file。 |
n >& m | 将输出文件 m 和 n 合并。 |
n <& m | 将输入文件 m 和 n 合并。 |
<< tag | 将开始标记 tag 和结束标记 tag 之间的内容作为输入。 |
文件描述符 0 通常是标准输入(STDIN),1 是标准输出(STDOUT),2 是标准错误输出(STDERR)。
command << delimiter
document
delimiter
# 功能是把两个delimiter之间的内容作为输入传递给command中
2
3
4
如果日志文件的格式为“userID:1 xxx”,“userID:2 xxx”等格式,你可以稍作修改以满足新的需求。以下是修改后的shell脚本示例:
#!/bin/bash
# 统计不同userID的次数
echo Count of occurrences by userID:
# 读取log.txt文件中的每一行
while read line
do
# 使用awk命令提取userID
user_id=$(awk -F':' '{print $1}' <<< $line)
# 使用grep命令统计user_id的出现次数
count=$(grep -o $user_id log.txt | wc -l)
# 输出userID和对应的次数
echo UserID $user_id: $count
done < log.txt
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
这段脚本会循环读取log.txt文件的每一行,提取userID并统计每个不同userID的出现次数。最后输出每个userID和对应的出现次数。你可以将上述代码保存为一个.sh文件并运行以执行脚本。
#include <iostream>
using namespace std;
struct listnode{
int val;
listnode *next;
listnode(){}
listnode(int v):val(v),next(nullptr){}
};
listnode* reverserL(listnode* head, int m, int n){
listnode ans;
ans.next=head;
listnode* it=&ans;
m--;
while(it&&m){
m--;
it=it->next;
}
listnode* p=it, *tail=it->next;
p->next = nullptr;
int a=n-m;
while(p&&tail&&a>1){
a--;
auto h = tail->next;
tail->next = p->next;
p->next = tail;
//p=p->next;
tail=h;
}
while(p->next){
p=p->next;
}
//cout<<tail->val;
p->next = tail;
//tail->next = nullptr;
// auto h=ans.next;
// while(h){
// cout<<h->val<<" ";
// h=h->next;
// }
return ans.next;
}
int main() {
listnode l1(1),l2(2),l3(3),l4(4),l5(5);
l1.next=&l2;
l2.next=&l3;
l3.next=&l4;
l4.next=&l5;
auto it = reverserL(&l1,2,4);
while(it){
cout<<it->val<<" ";
it=it->next;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61