一:linux使用
1.linux常用快捷键
Tab : 命令补全,当你忘记某个命令的全称时可以只输入它的开头的一部分,然后按下 Tab 键就可以得到提示或者帮助完成。
快捷键 | 作用 |
---|---|
Ctrl+c | 强行终止当前程序 |
Ctrl+d | 键盘输入结束或退出终端 |
Ctrl+s | 暂停当前程序,暂停后按下任意键恢复运行 |
Ctrl+z | 将当前程序放到后台运行,恢复到前台为命令fg |
Ctrl+a | 将光标移至输入行头,相当于Home键 |
Ctrl+e | 将光标移至输入行末,相当于End键 |
Ctrl+k | 删除从光标所在位置到行末 |
Alt+Backspace | 向前删除一个单词 |
Shift+PgUp | 将终端显示向上滚动 |
Shift+PgDn | 将终端显示向下滚动 |
你可以使用如下方式来获得某个命令的说明和使用方式的详细介绍:
$ man <command_name>
2.软件安装
*apt
自动下载,配置,安装软件包
APT由几个名字以“apt-”打头的程序组成。apt-get、apt-cache 和apt-cdrom是处理软件包的命令行工具
-
搜索:如果想在安装前确认是否软件库有这个软件:
sudo apt-cache search somesoftware
-
安装 :安装只需要执行这样的命令即可:
sudo apt-get install htop
当然它还有许多参数,例如在软件被破坏时重新安装:
sudo apt-get --reinstall install htop
-
更新:
更新软件源:
sudo apt-get update
更新代码块
sudo apt-get upgrade
- 卸载 :
sudo apt-get remove htop
如果连配置文件也想一并删除:
sudo apt-get purge htop
3.用户权限管理
1)查看用户
$ whoami
输出:当前伪终端的用户名
2)创建用户
首先使用 adduser 命令创建用户并设置密码:
$ sudo adduser <user>
su,su- 与 sudo :
$ su <user>
切换到用户 user,执行时需要输入目标用户的密码。
$ sudo <cmd>
以特权级别运行 cmd 命令,要求当前用户属于 sudo 组,且需要输入当前用户的密码。
$ su - <user>
切换用户,同时环境变量也会跟着改变成目标用户的环境变量。
3)查看用户组
$ groups user
输出为 用户 : 用户组。
4)删除用户
$ sudo deluser user --remove-home
4.文件权限管理
1)查看文件权限
ls
命令不仅可以列出并显示当前目录的文件,还可以用来查看文件的权限。
ls 选项 路径
选项:
-a:表示显示所有的文件/文件夹(包含了隐藏文件/文件夹)
在Linux中隐藏文件一般都是以“.”开头
-l:表示list,表示以详细列表的形式进行展示
-h:显示文档大小
##可以混合物使用,也可以指定路径,二者皆为非必填项
文件类型和权限:
第一位是指文件类型,例如 ‘d’ 表示目录, '-'表示普通文件,等等
后面的九位可以分成三组,每组三位分别表示
读权限/写权限/执行权限,
**三组分别对应的是 **
拥有者权限/所属用户组权限/其他用户权限。
2)变更文件所有者
$ sudo chown new_owner file
3)修改文件权限
方式一:二进制数字表示
每个文件的三组权限对应一个 “rwx”,每一位可以用 0 或 1 表示是否有权限
例如:只有读和写权限的话就是 “rw-” - “110”,所以"rwx"对应的二进制"111"就是十进制的7。
所以将 file 文件权限改为 “rwx------” 的命令是:
$ chmod 700 file
方式二:加减赋值表示
假设一开始 file 文件的权限是 “rwxr–r–” 完成上述同样的效果,还可以:
$ chmod go-rr file
g、o 还有 u 分别表示 group、others 和 user,+ 和 - 分别表示增加和去掉相应的权限。
5.目录文件及其操作
1)基本目录操作
cd 切换目录
. 表示当前目录
.. 表示上一级目录
pwd 获取当前目录的绝对路径
# cd ../.. 获取上两级目录
搭配之前提及的快捷键 Tab 可以大大提高效率
2)基本文件操作
*创建
命令 | 作用 |
---|---|
touch | 创建一个新的空白文件 |
mkdir | 创建一个新的目录。创建名为“ mydir ”的空目录: $ mkdir mydir |
注 mkdir:
[-p]:可以创建多层级目录,如:mkdir -p home/linux/linux2,即自动创建不存在的父目录,适用于创建连续多层级的目录
*查看
命令 | 作用 |
---|---|
cat | cat Linux路径 |
more | 查看 |
二者不同之处:
cat直接讲内容全部显示出来
more支持翻页,如果文件的内容过多,就可以一页一页查看文件内容 ,通过空格翻页,按q退出翻页查看
*复制
命令 | 作用 |
---|---|
cp | 复制一个文件到指定目录。例如: $ cp myfile ../../mydir |
目录: 在复制文件的基础上加上 -r 参数即可。 例如: $ cp -r dir mydir |
语法:
cp [-r] 参数1 参数2
参数1:Linux路径,表示被复制的文件或文件夹
参数2:Linux路径,表示被复制的文件或文件夹要复制到的地方
*删除
命令 | 作用 |
---|---|
rm(remove files or directories) | 删除一个文件: $ rm test 目录:同样,删除目录也是需要加上 -r 参数。 |
语法:
rm [-r -f] 参数1 参数2……参数n== ==
1.同cp命令一样,-r选项用于删除文件夹
2.-f表示force,强制删除==(不会弹出提示确认信息)==
3.普通用户删除内容不会弹出提示,只有root管理员用户删除内容会有提示,故普通用户一般用不到-f选项
4.参数1、参数2、……、参数n表示要删除的文件或文件夹路径,用空格隔开
rm命令支持通配符,用来做模糊匹配*
符号*表示通配符,即匹配任意内容(包括空)
test*:表示匹配任何以test开头的内容
*test:表示匹配任何以test结尾的内容
*test *:表示匹配任何包含test的内容
————————————————
关于强制删除(-f)
通过su -root,在输入密码之后临时切换到root用户
输入exit命令,退回普通用户(不要一直使用root用户权限)
rm是一个非常危险的命令,特别在处于root用户时
如下命令,千万不可以在root用户下执行
rm -rf /
rm -rf /*
效果等同于在Windows系统中执行C盘格式化
*移动及重命名
命令 | 作用 |
---|---|
mv (移动) | mv 源目录文件 目的目录: $ mv myfile mydir 注意,这里mv命令是剪切文件。 |
mv(重命名) | mv 旧的文件名 新的文件名:$ mv myfile myfile1 |
*编辑文件
命令 | 作用 |
---|---|
Linux系统存在许多编辑器,例如vim,emacs,nano等等 | 例:使用nano编辑器来打开文件:$ nano myfile |
6.搜索文件(which,whereis,locate,find)
1. which
which只从环境变量指定的路径中去搜索文件,所以我们常常使用which来判断是否安装了某个软件。
例如:$ which nano
2. whereis
直接从数据库而不是硬盘查询,而且只能搜索特定的文件
3. locate
" /var/lib/mlocate/mlocate.db "数据库由系统每天定时维护更新,所以有时候需要手动执行 updatedb 命令来更新数据库
locate 命令就是通过这个数据库查找的
例如,查找 /usr 及其子目录下所有以 a 开头的文件:
$ locate /usr/a
4. find
基本命令格式为:
find [path] [option] [action]
例如,在 /usr/ 目录下搜索名字为 myfile 的文件或目录:
$ sudo find /usr/ -name myfile
语法:find 起始目录 -name “被查找的文件名”
如:find / -name “test”
还可以按文件大小查找文件
语法:find 起始路径 -size +|- n[kMG]
+、-表示大于和小于
n表示大小数字
kMG表示大小单位,k(小写字母)表示kb,M表示MB,G表示GB
如:查找大于100MB的文件:find / -size =100M
7.文件解压器
*rar
-
创建压缩文件:
rar a ehpc.rar ./Desktop/
这是将ehpc目录打包成ehpc.rar
-
使用 a 参数添加文件进压缩包:
rar a ehpc.rar a.o
-
使用 d 参数删除文件:
rar d ehpc.rar a.o
-
使用 l 参数查看文件:
rar l ehpc.rar
-
解压分为两种,一种是 x 参数解压,这样会保持压缩文件的目录结构;另一种是 e 参数解压,将所有文件解压到当前目录:
unrar x ehpc.rar unrar e ehpc.rar
*zip
-
创建压缩包:
zip -r -o ehpc.zip ./Desktop
其中,-r 参数表示递归,所以上面命令是打包ehpc目录进压缩包;-o 参数表示输出到ehpc.zip压缩文件。 -
使用 -e 参数进行加密:
zip -r -e -o ehpc.zip ./Desktop
需要注意的是,由于编码问题linux下和windows下的文本文件可能会不同,如果希望在linux压缩的文件在windows下正常解压,可以加上 -l 参数。
-
查看与解压
解压很简单:
unzip ehpc.zip
查看只需加上 -l 参数:
unzip -l ehpc.zip
*tar
[注] tar 原本只是一个打包工具,没有压缩功能,需要配合其他具有压缩功能而没有打包功能的工具进行打包压缩
-
创建一个 tar 包:
tar -cf ehpc.tar ./Desktop
其中,-c 参数表示创建,-f 参数表示指定文件名,必须跟在文件名之前。可以发现这个tar包和原大小相同
-
查看一个 tar 包:
tar -tf ehpc.tar
-
解包一个 tar 包到指定目录:
tar -xf ehpc.tar -C ehpcdir
-
上面我们说了tar需要配合其他工具进行压缩,其实一般只需要加一个参数就可以了。这里以gzip为例:
tar -czf ehpc.tar.gz ./
解压缩:
tar -xzf ehpc.tar.gz
8.管道和一些文本命令
*grep
从文件中通过关键字过滤文件行
语法:grep [-n] 关键字 文件路径
-
选项-n,可选,表示在结果中显示匹配的行的行号
-
关键字,表示过滤的关键字,带有空格或其它特殊符号,建议使用“ ”将关键字包围起来
grep -r "ehpc" ~
搜索 ~ 目录下所有包含"ehpc"的文件 -
文件路径,表示要过滤内容的文件路径,可作为内容输入端口
*wc
统计并输出一个文件中行、字节等数据的数目。其中,
-l 参数表示行数,
-c 参数表示字节数
-m表示统计字符数量
-w表示统计单词数量
结合管道使用,统计文件的个数:
ls -a | wc -l
*uniq
在上面的统计中,我们可能会想要除去一些重复行以免影响结果,这时候我们可以使用 uniq 命令:
cat words | uniq
[注]uniq只除去连续重复的的行
如果希望全文达到同样的效果我们往往会先使用 sort 命令进行排序,即:
cat words | sort | uniq
*echo
可以使用echo命令在命令行内输出指定内容
语法:echo 输出的内容
- 关键字,表示过滤的关键字,带有空格或其它特殊符号,建议使用“ ”将关键字包围起来
反引号:``
被``包围的内容将会被作为命令执行
*tail
使用tail命令,可以查看文件尾部内容,跟踪文件的最新更改
语法:tail [-f -num] Linux路径
- -f:表示持续追踪
- -num:表示查看尾部多少行,不填则默认10行
*管道符
含义:将管道符左边命令的结果,作为右边命令的输入
&&和||
&& 表示如果前一个命令返回的状态为0(这些状态码有一套默认的规定),则执行后一个命令,否则不执行。而 || 则与之相反。
例如我们常常使用 which 命令来判断是否安装了某个命令:
which rar>/dev/null && echo "Installed."
当然也可以结合使用:
which rar>/dev/null && echo "Installed." || echo "Not installed"
9.文本处理
*sort
根据不同的标准来排序,例如:
默认为字典排序:
ls -a | sort
反转排序:
ls -a | sort -r
*col
tab和空格相互转换
-x 参数表示将 tab 转换成空格,而 **-h **参数则相反。
例如:
cat myFile | col -x | cat -A
*tr
替换操作(删除操作也可以视为一种替换操作)
- 如果是要删除,可以使用 -d 参数:
`echo “Hello world!” | tr -d "el"这样会删除"Hello world!"中所有的“e”和“l”. - 再例如将小写转换成大写:
echo "Hello world!" | tr '[a-z]' '[A-Z]'
*paste
这个命令可以简单地合并文件。
例如将数据以 ‘;’ 为分隔符合并(默认的分隔符为Tab):
paste -d ';' data1 data2 data3
10.重定向
1)重定向
-
`>和>>
`>:将左侧命令的结果,覆盖写入到符号右侧指定的文件中
`>>:将左侧命令的结果追加写入到符号右侧指定的文件中
2)文件描述符
除了标准输出,我们还经常需要重定向标准错误,在此就必须提到标准输入、标准输出和标准错误的文件描述符。在linux中,它们的文件描述符分别是0、1、2,我们可以通过这几个描述符来完成我们想要的操作。
我们可以这样来将标准输出和标准错误重定向到同一个文件:
cat words | sort | uniq > output 2>&1
其中,&表示后面的是标准输出而不是一个文件名为1的文件,而这里的重定向顺序也是不能改变的。
也可以这么做:
cat words | sort | uniq &> output
3)永久重定向以及“丢弃”输出
- 永久重定向(不那么永久)
exec 1> output
其中 exec 命令的作用是用新的进程去替换旧的进程,或者指定重定向。
- 有时候我们仅仅希望执行命令而不想要其输出,这时候我们可以将输出重定向到空设备 /dev/null :
cat words | sort | uniq 1>/dev/null 2>&1
这样输出结果就没有啦。
11.进程的基本操作
1)前台/后台切换
-
当前进程停止并转到后台的快捷键是 ctrl + z
-
终止一个在前台运行的进程的快捷键是 ctrl + c
-
进程在前台与后台之间切换:
& 这个符号,让我们的命令在后台中运行。
例如:
ls &
-
查看在后台的工作:
可以使用jobs
这时我们可以看到每行是这样的格式:
[1] + suspended ...(command)
第一列的数字表示job编号,也就是转到后台的工作的编号,第二列如果是 ‘+’ 表示的是这是最后一个被转入后台的工作, ‘-’ 的话则是倒数第二个,其他的话在这列没有符号。第三列表示状态,而后面则是命令本身
-
后台拿回前台怎么办呢?
可以使用
fg %jobid
例如,fg %1
-
只是希望其在后台运行:
bg %jobid
2)终止
参数-l查看信号值:kill -l
所以可以这样终止程序:
kill -signal pid
或者
kill -signal %jobid
12.进程管理
*top
top 命令是我们常常使用查看工具,它可以实时查看系统的一些关键信息的变化。
top 命令的输出比较多,下面逐一介绍:
第一行:
当前程序名称 当前系统时间 机器启动时间 系统用户数量 1分钟内、5分钟内和15分钟内cpu平均负载
第二行:
进程总数 正在运行的进程数 休眠的进程数 停止的进程数 僵尸进程数
第三行:
用户空间占用CPU百分比
内核空间占用CPU百分比
用户空间优先级变化的进程占用CPU百分比
空闲CPU百分比
等待IO的CPU时间百分比
硬中断占用CPU的百分比
软中断占用CPU的百分比
虚拟 CPU 等待物理 CPU 的时间的百分比
第四行:
物理内存总量
使用物理内存总量
空闲内存总量
缓存内存总量
第五行:
交换区总量
使用交换区总量
空闲交换区总量
缓冲交换区总量
然后就是许多行进程的信息了,以下按顺序分别对应:
PID:进程id
USER:进程所属用户
PR:进程动态优先级值
NI:进程静态优先级值
VIRT:进程使用虚拟内存总数
RES:进程使用物理内存数
SHR:进程共享内存大小
S:进程状态
%CPU:CPU利用率
%MEM:内存利用率
TIME+:进程活跃总时间
COMMAND:进程运行名
我们甚至可以与这个程序交互,例如输入k的话系统会提示进一步输入信号值以及pid号以杀死一个进程.
*ps
ps aux 这个命令将会列出所有的进程信息。
往往配合 grep 和正则表达式使用。
例如:
ps aux | grep slurm
打印的信息:
F:进程的标志(process flags),当 flags 值为 1 则表示此子程序只是 fork 但没有执行 exec,为 4 表示此程序使用 root 权限
USER:进程拥有者
PID:进程ID
PPID:父进程的PID
SID:session 的ID
TPGID:前台进程组的ID
%CPU:进程占用的CPU百分比
%MEM:占用内存的百分比
NI:进程的 NICE 值
VSZ:进程使用虚拟内存大小
RSS:驻留内存中页的大小
TTY:终端ID
S or STAT:进程状态
WCHAN:正在等待的进程资源
START :启动进程的时间
TIME:进程消耗CPU的时间
COMMAND:命令的名称和参数
查看进程树:
pstree
二:Vim的使用
1.基本模式
1)普通模式
直接使用vim命令后进入vim的普通模式,在其他模式下,按下ESC
或者Crtl+[
即可返回普通模式。
2)插入模式
在普通模式下等键即可进入插入模式,插入模式下,按键则会输入。例如我们输入:i, I, a, A``ehpc
3)可视模式
在普通模式下,按下即可进入:v, V, <Ctrl>+v
4)命令行模式
在普通模式下,按下即可进入::
5)Ex模式
在进入Vim时,加上参数即可进入,例如::-e``vim -e
2.普通模式–游移光标
1)字符级移动
在普通模式下,可以使用方向键或者进行移动,如下表:h,j,k,l
按键 | 方向 |
---|---|
h,← | 左 |
l,→ | 有 |
j,↓ | 下 |
k,↑ | 上 |
2)行内移动
在行内以移动游标时,可以使用下面的命令来实现:
按键 | 说明 |
---|---|
w | 右移到下一个单词的开头 |
e | 右移到下一个单词的末尾 |
b | 左移到前一个单词的开头 |
0 | 右移到本行的开始 |
$ | 右移到本行的末尾 |
^ | 左移到本行的第一个非空字符 |
3)页级移动
可以在相邻页之间移动:
按键 | 说明 |
---|---|
crtl +f | 前移一页 |
crtl +b | 后移一页 |
4)页内移动
当我们到达指定页时,可以在页内快速移动:
按键 | 说明 |
---|---|
H | 将光标移到该页的起始行 |
M | 将光标移到该页的中间行 |
L | 将光标移到该页的末尾行 |
5) 其他移动
Vim提供了很多的移动方式,这里再列举一些大范围移动:
按键 | 说明 |
---|---|
* | 将光标移到该单词的下一个位置 |
# | 将光标移到该单词的上一个位置 |
g | 将光标移到文件的第一行 |
G | 将光标移到文件的末尾行 |
3.文档编辑
1) 搜索
Vim的搜索方法非常简单,只需要输入+就可以进行搜索,其命令具体如下:/``内容
指令 | 说明 |
---|---|
\ +str | 向下搜索字符串str |
n | 继续搜索 |
N | 反向搜索 |
? +str | 反向搜索字符串str |
尝试使用命令搜索,ephc``vmi
2 )替换
Vim的常规替换命令主要由和完成,但替换命令之后,会进入插入模式,按下即可返回普通模式,替换命令部分如下:s``c``ESC
指令 | 说明 |
---|---|
s | 用输入的正文替换游标所在的字符 |
ns | 用输入的正文替换游标右侧个字符n |
c$ | 用输入的正文替换从游标开始到行尾的所有字符 |
c0 | 用输入的正文替换从本行开始到游标的所有字符 |
3) 删除
Vim的删除命令主要由和完成,如下:d``x
指令 | 说明 |
---|---|
x | 删除游标所在的字符 |
X | 删除游标所在前一个字符 |
dw | 删除游标右的单词 |
dd | 删除游标所在行 |
d0 | 删除光标到行的开始 |
d$ | 删除光标到行的末尾 |
4) 复制
Vim中删除操作其实与剪切操作类似,会将内容复制到内存缓冲区,当然,也可以通过命令自行复制而不删除内容:
指令 | 说明 |
---|---|
yy | 复制游标所在行到缓冲区 |
nyy | 复制行到缓冲区n |
5) 粘贴
将内容复制到缓冲区后,可以使用命令将内容粘贴:
指令 | 说明 |
---|---|
p | 粘贴到游标后 |
P | 粘贴到游标前 |
6) 撤销
通过指令,可以撤销上一次的操作:
指令 | 说明 |
---|---|
u | 撤销上次操作 |
7) 重复
通过指令,可以重复上一次的操作:
指令 | 说明 |
---|---|
u | 重复上次操作 |
4.命令模式
首先,使用进入Vim,要进入命令模式,只需输入后·,即可进入,此时游标在屏幕最后一行:vim``:
1) 打开文件
在进入Vim之后,如需打开其他文件,命令未+,例如:
则可打开ehpc.txt文件e``文件名``:e ehpc.txt
2) 保存文件
编辑之后,我们可以使用命令保存文件,也可以另存为其他文件:w
:w other-ehpc.txt
3) 退出Vim
退出Vim时,如果未作修改,需要使用进行退出,如果有修改内容,但不保存,则可以使用强制退出,如果想要保存内容,并退出,可以使用命令。q``q!``wq
4) 行号操作
命令模式下,我们可以直接输入行号进行跳转:
:跳转到第行
通过对行号的使用,我们可以结合其他命令做到:: n``n
:nw 文件名
将行写入文件n
:m,nw 文件名
将到行写入文件m``n
:m,.w 文件名
将到当前行写入文件m
:.,$w 文件名
将当前行到最后一行写入文件
5) 文件操作
前面指出了可以使用打开文件,写文件,Vim还有更多的文件操作:e``w
:r 文件名
读取文件并插入到游标之后:f 文件名
重命名文件:f
输出当前文件名称和状态
6) 内容替换
Vim除了在普通模式下能够进行替换操作,命令模式下也可以进行替换操作:
:%s/str1/str2/
用替换行中首次出现的str2``str1
- 通过参数可以达到替换所有的操作:
用替换行中出现的g``:s/str1/str2/g``str2``str1
- 还可以指定行数,例如:
用字符串 替换正文中所有出现的字符串
上述操作也可以通过实现:1,$ s/str1/str2/g``str2``str1``:g/str1/s//str2/g
5.进阶命令
1)文件恢复
通过可以恢复意外退出而没有保存的文件:recover
2) 选项设置
通过命令可以设置选项,比如::set
选项 | 说明 |
---|---|
autoindent | 自动缩进 |
number | 显示行号 |
ignorecase | 忽略正则表达式的大小写 |
ruler | 显示游标位置 |
3) 分屏
Vim中可以使用命令进行分屏操作:
命令 | 说明 |
---|---|
split ,sp | 水平分屏 |
vsplit ,vsp | 垂直分屏 |
也可以在启动Vim时分屏,在启动时加入参数: 打开 file1 和 file2 ,垂直分屏
打开 file1 和 file2 ,水平分屏
各屏幕间移动需要使用快捷键:
vim -On file1 file2...``vim -on file1 file2...
命令 | 说明 |
---|---|
Ctrl +w +h | 当前屏的左分屏 |
Ctrl +w +l | 当前屏的右分屏 |
Ctrl +w +j | 当前屏的下分屏 |
Ctrl +w +k | 当前屏的上分屏 |
4) 差异
可以通过Vim进行不同文件之间的比较,在命令行中,可以直接输入即可在Vim里分屏显示两个文件的差异。
在Vim内,也可以通过命令与其他文件进行比较vimdiff file1 file2``diffsplit file
5) Vim插件
Vim本身已经具有丰富的功能,但是通过插件的安装,甚至可以自定义得到IDE。
三:简单的shell语法
四:编译运行程序:判断回文质数
源代码:
from math import sqrt
number = int(input('请输入一个质数: '))
def is_prime(num):
for i in range(2, int(sqrt(num)+1):
if num % i == 0:
return False
return True if num != 1 else False
def is_palindrome(num):
x = num
sum = 0
while x > 0
sum = sum * 10 + x % 10
x // = 10
return num == sum
if is_prime(number) and is_palindrome(number):
print('%d是回文质数' % number)
else :
print('%d不是回文质数' % number)
运行结果:
五:栈和队列及中缀改后缀的练习
1.栈和队列
2.中缀改后缀
*将中缀表达式转化成对应的后缀表达式 所谓后缀表达式是指这样的一个表达式:式中不再引用括号,运算符号放在两个运算对象之后,所有计 算按运算符号出现的顺序,严格地由左而右进行(不用考虑运算符的优先级) 例1:中缀表达式: 3(5–2)+7 对应的后缀表达式为:352-7+ 例2:中缀表达式: 2+48+(88+1)/3 对应的后缀表达式为 248+881+3/+ 考察内容:栈的基本使用
expression = input("输入表达式: ")
def middle2behind(expression):
result = [] # 输出结果表达式
stack = [] # 创建栈
for item in expression:
if item.isnumeric(): # 当前字符为数字直接进入结果列表
result.append(item)
else: # 其他操作符
if len(stack) == 0: # 空栈则直接入栈
stack.append(item)
elif item in'*/(': # 当前字符为*/( 直接入栈
stack.append(item)
elif item == ')': # 右括号则全部弹出至碰到左括号为止
t = stack.pop()
while t != '(':
result.append(t)
t = stack.pop()
# 如果当前字符为加减且栈顶为乘除,开始弹出
elif item in '+-' and stack[len(stack)-1] in '*/':
if stack.count('(') == 0: # 弹出至有左括号出现为止,如果有左括号的话
while stack:
result.append(stack.pop())
else: # 没有左括号,全部弹出
t = stack.pop()
while t != '(':
result.append(t)
t = stack.pop()
stack.append('(')
stack.append(item) # 弹出后将'+-'入栈
else:
stack.append(item) # 其余情况直接入栈
# 遍历完,将栈中剩余字符弹出
while stack:
result.append(stack.pop())
# 返回字符串
return "".join(result)
print(middle2behind(expression))