Shell编程实例——bash的配置与自定义(一)

Bash Shell编程基础 转载请注明出处:http://blog.youkuaiyun.com/u012842205/article/details/79584275一、Shell是什么1)Shell是操作系统提供的,供用户调用的操作接口。分命令行调用接口(CLI)和图形用户接口(GUI)。2)在Unix历史中,Shell作为系统的命令行调用接口,以独立的程序实现。3)早期的Shell提供了一些基本特性,供用户使用。功能逐渐完善,发展... 阅读详情

1、bash启动选项

你想搞清楚 bash 的各种启动选项,但是 bash --help 也没能帮上忙。

除了 bash --help,还可以试试 bash -c “help set” 和bash -c help,如果正在使用 bash shell,直接使用 helpset 和 help 就行了。

bash 有时可以采用不同的方式设置相同的选项,这就是一个例子。你可以在启动时设置某个选项(如 bash -x)​,随后使用 set +x 以交互形式关闭该选项。

2、自定义提示符

默认的 bash 提示符通常以 $ 结尾,但信息不够丰富,传达不出太多的东西。你希望能够自定义提示符,以展现出更多实用的信息。

根据需要自定义 $PS1 和 $PS2 变量。

默认的提示符随系统而异。bash 本身会显示其主版本号和次版本号(\s-\v\$)​,例如,bash-3.00$。不过,你的操作系统可能有自己的默认提示符,例如,有些版本的Fedora 使用的是 [user@host~]$ ([\u@\h\W]\$)。这里我们给出了 8 种基本提示符和 3 种花哨的提示符。

  • 基本提示符:以下这 8 种更实用的提示符适用于 bash 1.14.7 及以上版本。如果有效 UID 为 0(root 用户)​,结尾的 $显示为 #;否则显示为 $。

    • 用户名 @ 主机名、日期和时间,以及当前工作目录。
      $ export PS1='[\u@\h \d \A] \w \$ '
      [jp@freebsd Wed Dec 28 19:32] ~ $ cd /usr/local/bin/
      [jp@freebsd Wed Dec 28 19:32] /usr/local/bin $
      
    • 用户名 @ 长格式主机名、ISO 8601 格式的日期和时间,以及当前工作目录的基本名称(\W)​。
      $ export PS1='[\u@\H \D{%Y-%m-%d %H:%M:%S%z}] \W \$ '
      [jp@freebsd.jpsdomain.org 2005-12-28 19:33:03-0500] ~ $ cd /usr/local/
      [jp@freebsd.jpsdomain.org 2005-12-28 19:33:06-0500] local $
      
    • 用户名 @ 主机名、bash 版本号,以及当前工作目录(\w)​。
      $ export PS1='[\u@\h \V \w] \$ '
      [jp@freebsd 3.00.16] ~ $ cd /usr/local/bin/
      [jp@freebsd 3.00.16] /usr/local/bin $
      
    • 换行符、用户名 @ 主机名、基本 PTY、shell层级、历史编号、换行符,以及完整的工作目录名称($PWD)​。
      $ export PS1='\n[\u@\h \l:$SHLVL:\!]\n$PWD\$ '
      
      [jp@freebsd ttyp0:3:21]
      /home/jp$ cd /usr/local/bin/
      
      [jp@freebsd ttyp0:3:22]
      /usr/local/bin$
      
      PTY 是你所连接的伪终端(Linux 术语)的编号。当你有多个会话并且试图跟踪各个会话时,这就能派上用场了。shell 层级是你所在子 shell 的深度。首次登录时,这个值是 1,随着不断地生成子进程(如 screen)​,该值也会不断增加,因此,运行 screen 之后,值就变成了 2。历史编号是当前命令在命令历史记录中的编号。
    • 用户名 @ 主机名、上一个命令的退出状态,以及当前工作目录。注意,只要在提示符下执行任何命令,退出状态就会被重置(因此也就失去了作用)​。
      $ export PS1='[\u@\h $? \w \$ '
      [jp@freebsd 0 ~ $ cd /usr/local/bin/
      [jp@freebsd 0 /usr/local/bin $ true
      [jp@freebsd 0 /usr/local/bin $ false
      [jp@freebsd 1 /usr/local/bin $ true
      [jp@freebsd 0 /usr/local/bin $
      
    • 换行符、用户名 @ 主机名,以及 shell 当前管理的作业数。如果运行了大量的后台作业,又把这事给忘了,该提示符就能发挥作用了。
      $ export PS1='\n[\u@\h jobs:\j]\n$PWD\$ '
      
      [jp@freebsd jobs:0]
      /tmp$ ls -lar /etc > /dev/null &
      [1] 96461
      
      [jp@freebsd jobs:1]
      /tmp$
      [1]+ Exit 1             ls -lar /etc >/dev/null
      
      [jp@freebsd jobs:0]
      /tmp$
      
    • 换行符、用户名 @ 主机名、终端、shell 层级、历史编号、作业数量、bash 版本号,以及完整的工作目录。
      $ export PS1='\n[\u@\h t:\l l:$SHLVL h:\! j:\j v:\V]\n$PWD\$ '
      
      [jp@freebsd t:ttyp1 l:2 h:91 j:0 v:3.00.16]
      /home/jp$
      
    • 换行符、用户名 @ 主机名、代表终端的 T、代表 shell 层级的 L、代表命令编号的 C,以及 ISO 8601 格式的日期和时间。
      $ PS1='\n[\u@\h:T\l:L$SHLVL:C\!:\D{%Y-%m-%d_%H:%M:%S_%Z}]\n$PWD\$ '
      
      [jp@freebsd:Tttyp1:L1:C337:2006-08-13_03:47:11_EDT]
      /home/jp$ cd /usr/local/bin/
      
      [jp@freebsd:Tttyp1:L1:C338:2006-08-13_03:47:16_EDT]
      /usr/local/bin$
      
      这属于那种让人非爱即恨的提示符。它清晰无误地显示了谁在什么时间什么地点做了什么,非常适合在回滚缓冲区(scrollbackbuffer)中通过简单地复制和粘贴来记录执行某项任务的步骤,但有些人认为这种提示符的形式太杂乱,容易分散注意力。
  • 花哨的提示符:下列 3 种花哨的提示符要么使用 ANSI 转义序列来显示颜色,要么在 xterm 中设置标题栏的内容,但要注意,这些做法未必总能奏效。

    系统设置、xterm 仿真,以及 SSH 和 Telnet 客户端中都存在大量让人摸不着头脑的变量,它们都可能影响到这些提示符。

    另外还要注意,转义序列应该出现在 [ 和 ] 的内部,以此告知 bash 其中的字符不可打印。否则,bash(从技术上来说其实是 readline)会搞不清楚行的长度,在错误的位置上折行。

    • 用户名 @ 主机名、浅蓝色的当前工作目录(实体书上看不出颜色)​。
      $ export PS1='\[\033[1;34m\][\u@\h:\w]\$\[\033[0m\] '
      [jp@freebsd:~]$
      [jp@freebsd:~]$ cd /tmp
      [jp@freebsd:/tmp]$
      
    • 在 xterm 的标题栏和提示符中同时显示用户名 @ 主机名、当前工作目录。如果你使用的不是 xterm,则可能会在提示符中产生一些乱七八糟的东西。
      $ export PS1='\[\033]0;\u@\h:\w\007\][\u@\h:\w]\$ '
      [jp@ubuntu:~]$
      [jp@ubuntu:~]$ cd /tmp
      [jp@ubuntu:/tmp]$
      
    • 同时更新颜色和 xterm。
      $ PS1='\[\033]0;\u@\h:\w\007\]\[\033[1;34m\][\u@\h:\w]\$\[\033[0m\] '
      [jp@ubuntu:~]$
      [jp@ubuntu:~]$ cd /tmp
      [jp@ubuntu:/tmp]$
      

为了让你在逐个尝试时免去烦人的输入,所有这些提示符都可以在本书的 GitHub 仓库中找到(文件 ./ch16/prompts)​。下例展示了该文件的内容。

# 实例文件:prompts

# 用户名@短格式主机名、日期和时间,以及当前工作目录(CWD):
export PS1='[\u@\h \d \A] \w \$ '

# 用户名@长格式主机名、ISO 8601格式的日期和时间、当前工作目录的基本名称(\W):
export PS1='[\u@\H \D{%Y-%m-%d %H:%M:%S%z}] \W \$ '

# 用户名@短格式主机名、bash版本号,以及当前工作目录(\w):
export PS1='[\u@\h \V \w] \$ '

# 换行符、用户名@短格式主机名、基本PTY、shell层级、历史编号、换行符,以及完整的工作
目录名称($PWD):
export PS1='\n[\u@\h \l:$SHLVL:\!]\n$PWD\$ '

# 用户名@短格式主机名、上一个命令的退出状态,以及当前工作目录:
export PS1='[\u@\h $? \w \$ '

# 换行符、用户名@短格式主机名,以及后台作业数:
export PS1='\n[\u@\h jobs:\j]\n$PWD\$ '

# 换行符、用户名@短格式主机名、终端、shell层级、历史编号、作业数量、bash版本号,以
及完整的工作目录:
export PS1='\n[\u@\h t:\l l:$SHLVL h:\! j:\j v:\V]\n$PWD\$ '

# 换行符、用户名@短格式主机名、代表终端的T、代表shell层级的L、代表命令编号的C,以及
ISO 8601格式的日期和时间:
export PS1='\n[\u@\h:T\l:L$SHLVL:C\!:\D{%Y-%m-%d_%H:%M:%S_%Z}]\n$PWD\$ '

# 用户名@短格式主机名、浅蓝色的当前工作目录:
export PS1='\[\033[1;34m\][\u@\h:\w]\$\[\033[0m\] '

# 在xterm的标题栏和提示符中同时显示用户名@短格式主机名、当前工作目录:
export PS1='\[\033]0;\u@\h:\w\007\][\u@\h:\w]\$ '

# 同时更新颜色和xterm:
export PS1='\[\033]0;\u@\h:\w\007\]\[\033[1;34m\][\u@\h:\w]\$\[\033[0m\] '

注意,export 命令只需要使用一次,就可以标记出要导入子进程的变量。

假设已经设置 shell 选项 promptvars(默认情况)​,提示字符串会被解析和扩展(通过变量扩展、命令替换以及算术扩展)​、引号会被移除并显示最终结果。提示字符串分别为 $PS0、 P S 1 、 ‘ PS1、` PS1、‘PS2、 P S 3 ‘ 、 ‘ PS3`、` PS3‘、‘PS4`。

  • $PS0 仅存在于 bash 4.4 及以上版本。下一节将详细讨论这个“执行前”​(preexecution)提示符。
  • $PS1 是命令提示符。
  • $PS2 是辅助提示符,在 bash 需要更多信息来结束命令时,它会出现。该提示符默认为 >,但你也可以改用其他字符。
  • $PS3 是 select 提示符(参见 3.7 节和 6.16 节)​,其默认为 #?。
  • PS4 是 xtrace(调试)提示符,其默认为 +。注意,$PS4 的首个字符会根据需要重复多次,以表明当前所执行命令的嵌套级数。
$ export PS2='Secondary> '

$ for i in *
Secondary> do
Secondary> echo $i
Secondary> done
cheesy_app
data_file
hard_to_kill
mcd
mode

$ export PS3='Pick me: '

$ select item in 'one two three'; do echo $item; done
1) one two three
Pick me: ^C

$ export PS4='+ debugging> '

$ set -x

$ echo $( echo $( for i in *; do echo $i; done ) )
+++ debugging> for i in '*'
+++ debugging> echo cheesy_app
+++ debugging> for i in '*'
+++ debugging> echo data_file
+++ debugging> for i in '*'
+++ debugging> echo hard_to_kill
+++ debugging> for i in '*'
+++ debugging> echo mcd
+++ debugging> for i in '*'
+++ debugging> echo mode
++ debugging> echo cheesy_app data_file hard_to_kill mcd mode
+ debugging> echo cheesy_app data_file hard_to_kill mcd mode
cheesy_app data_file hard_to_kill mcd mode

由于仅以交互方式运行 bash 时才有用,因此 $PS1 提示符的最佳设置位置是在全局文件 /etc/bashrc 或者本地文件 ~/.bashrc 中。

从风格角度而言,我们建议将空格作为 $PS1 字符串的最后一个字符。把提示字符串与用户输入的命令隔开,更易于阅读屏幕上的内容。有鉴于此,又因为提示字符串中可能包含其他空格或特殊字符,所以最好使用双引号或单引号将其引用起来,再赋给 $PS1。

至少有 3 种简单易行的方式可以在提示符中显示当前工作目录(CWD)​:\w、\W、$PWD。\W 输出基本名称,或者说是目录路径的最后一部分,\w 则输出整个路径。注意,当你位于主目录时,两者输出的都是 ~,而非 $HOME的值。这让有些用户着实抓狂,因此,要想输出完整的当前工作目录,可以使用 $PWD。输出完整的当前工作目录会改变提示符的长度,在比较深的目录层次结构中,这会使得提示符折行。这又让另一些用户抓狂了。对于 bash 4或以上版本,使用 $PROMPT_DIRTRIM 并配合 \w 或 \W即可(不会影响 $PWD)​。Bash Reference Manual 中对该变量的描述如下。

如果设置为大于 0 的数字,那么在扩展 \w 和 \W提示字符串转义时,将该值作为要保留的结尾目录组件的数量…… 被删除的那些字符以省略号替换。

如果能使用 $PROMPT_DIRTRIM,那就用;如果无法使用,下例中给出了一个可用于截断工作目录的函数及其用法提示。

# 实例文件:func_trunc_PWD

function trunc_PWD {
    # $PWD截断代码改编自The Bash Prompt HOWTO:
    # 11.10. Controlling the Size and Appearance of $PWD

    # $PWD中有多少个字符应该保留
    local pwdmaxlen=30
    # 表明目录已被截断的指示符
    local trunc_symbol='...'
    # PWD的临时变量
    local myPWD=$PWD

    # 用'~'替换$PWD中匹配$HOME的部分
    # 如果想使用完整路径,可以将下面这条语句注释掉!
    myPWD=${PWD/$HOME/~}

    if [ ${#myPWD} -gt $pwdmaxlen ]; then
        local pwdoffset=$(( ${#myPWD} - $pwdmaxlen ))
        echo "${trunc_symbol}${myPWD:$pwdoffset:$pwdmaxlen}"
    else
        echo "$myPWD"
    fi
}

接下来演示一下用法。

$ source file/containing/trunc_PWD

[jp@freebsd ttyp0:3:60]
~/this is a bunch/of really/really/really/long directories/did I mention really/
really/long$export PS1='\n[\u@\h \l:$SHLVL:\!]\n$(trunc_PWD)\$ '

[jp@freebsd ttyp0:3:61]
...d I mention really/really/long$

你可以注意到,这里的提示字符串出现在单引号内,因此,$ 和其他特殊字符会按照其字面意义被对待。提示字符串在显示期间求值,其中的变量会如期被扩展。双引号也不是不能用,但这样的话,你必须对 shell 元字符进行转义,例如,使用 $ 代替 $。

命令编号和历史编号通常不是一回事:命令的历史编号是其在历史列表中的位置,列表可能包含从历史文件中恢复的命令;而命令编号是在当前 shell 会话期间所执行的一系列命令中的位置。

另外还有一个特殊变量 $PROMPT_COMMAND,该变量(如果设置的话)会被解释为在求值并显示 $PS1 之前要执行的命令。此处以及在 $PS1 中使用命令替换的问题是,每次显示提示符时都会执行这些命令,这太频繁了。例如,你可以在提示符中嵌入 $(ls-l | wc-l) 这样的命令替换,以此获得当前工作目录内的文件数量。但对于比较陈旧或者使用率颇高的系统来说,如果位于包含大量文件的目录中,可能会导致在看到提示符并能够着手工作前出现明显的延迟。提示符最好简短明了(尽管本节中展示的部分提示符挺吓人的)​。如有需要,可以定义函数或别名,别搞得你的提示符又乱又慢。

为了解决提示符中出现的 ANSI 或 xterm 转义序列在不被支持的情况下产生乱七八糟的内容,你可以在 rc 文件中加入下列操作。

case $TERM in
     xterm*) export \
PS1='\[\033]0;\u@\h:\w\007\]\[\033[1;34m\][\u@\h:\w]\$\[\033[0m\]' ;;
              *) export PS1='[\u@\h:\w]\$ ' ;;
esac

在我们刚刚讨论的 ANSI 例子中,1;34m 代表“将字符属性设置为浅色,将字符颜色设置为蓝色”​。0m 代表“清除所有属性,不设置颜色”​。这些代码可参见 A.3 节。结尾的 m 表示颜色转义序列。

下例中的脚本展示了所有可能的组合。如果你的终端显示不出颜色,则表明未启用或不支持 ANSI 颜色。

#!/usr/bin/env bash
# 实例文件:colors
#
# Daniel Crisman的ANSI颜色图表脚本取自
# The Bash Prompt HOWTO: 6.1. Colours
#
# 该文件向终端回显了一批颜色代码,以演示可用的颜色。
# 每行分别选择17种前景色颜色代码(默认 + 16个转义序列)中的一种,
# 然后在所有9种背景色上测试该颜色(默认 + 8个转义序列)
#

T='gYw' # 测试文本

echo -e "\n                 40m     41m     42m     43m\
     44m     45m     46m     47m";

for FGs in '    m'   ' 1m' '  30m' '1;30m' '  31m' '1;31m' '  32m' \
           '1;32m' '  33m' '1;33m' '  34m' '1;34m' '  35m' '1;35m' \
           '  36m' '1;36m' '  37m' '1;37m'; do
    FG=${FGs// /}
    echo -en " $FGs \033[$FG  $T  "
    for BG in 40m 41m 42m 43m 44m 45m 46m 47m; do
        echo -en "$EINS \033[$FG\033[$BG  $T  \033[0m";
    done
    echo;
done
echo

3、在程序运行前出现的提示符

你想让提示符在程序运行前出现,而不只是在结束之后。这样可以方便地标记起止时间。

这个解决方案仅适用于 bash 4.4 或以上版本。这些版本中引入了 $PS0 提示符。如果设置的话,该提示字符串会在命令执行前被求值并输出。

接下来我们用 $PS0 和 $PS1 来显示命令运行的起止时间。

PS0='                                                \t\n'
PS1='----------------------------------------------- \t\n\! \$ '

P S 0 是执行前提示符。它会在 s h e l l 执行命令前显示。那些前导空白字符是为了将输出往右边挪动;如果觉得还不够靠右或想再往左边些,随意添加或删除空白字符即可。与此类似, PS0 是执行前提示符。它会在 shell 执行命令前显示。那些前导空白字符是为了将输出往右边挪动;如果觉得还不够靠右或想再往左边些,随意添加或删除空白字符即可。与此类似, PS0是执行前提示符。它会在shell执行命令前显示。那些前导空白字符是为了将输出往右边挪动;如果觉得还不够靠右或想再往左边些,随意添加或删除空白字符即可。与此类似,PS1 中的连字符也是为了将时间戳右移,同时在命令之间划定界限,以便更好地观察。你也可以根据需要添加更多的连字符(或改用空格)​。

这两个提示符中的关键在于 \t。它会转换成时间戳。\n 代表换行符,作用是更好地格式化。如果按照上述方法设置好提示符,然后执行一个得花费些时间的命令(如 sleep5)​,可以看到如下结果。

1037 $ echo 'sleep...' ; sleep 5; echo 'awake!'
                                                21:36:59
sleep...
awake!
----------------------------------------------- 21:37:04
1038 $

如果想让 $PS0 提示符和键入的命令出现在同一行,那就在 \t 前面加上 \e[A。为了让时间戳更往右移,你可能还得添加更多空格。

要想在设置之前先测试提示符,可以利用另一个仅 适用于 bash 4.4 或以上版本的特性。将提示字符串赋给某个变量,然后使用 @P 运算符输出该变量的值。例如:

$ MYTRY='    \! \h \t\n'
$ echo "${MYTRY}"
    \! \h \t\n
$ echo "${MYTRY@P}"
    1015 monarch 14:07:45

$

如果不使用 @P,输出的则是所键入的字符;加上@P 的话,则会按照提示字符串解释其中的特殊字符序列。如果显示效果如你所愿,就将其赋给$PS0。

时间戳的解析度只能到秒,并不适用于精确的性能测量,但在回顾一系列命令的来龙去脉(尤其离开屏幕去拿咖啡的情况下)以及哪些命令运行时间较长时非常有用。

4、永久修改$PATH

你需要永久性修改命令路径。

首先,你得找出在哪里设置路径,然后再修改。对于本地账户,可能是在~/.profile 或 ~/.bash_profile 中。用 grep-l PATH ~/.[^.]* 找出该文件并使用你喜欢的编辑器进行修改。接着对文件使用 source 命令,使改动立即生效。

如果你是 root 用户,则需要设置整个系统的路径,基本操 作过程是一样的,但 /etc 目录中可供设置 $PATH 的文件不尽相同,具体取决于你的操作系统和版本。最有可能的文件是 /etc/profile,但也有可能是/etc/bashrc、/etc/rc、/etc/default/login、~/.ssh/environment 以及 PAM 的 /etc/environment。

某些系统中有一个名为 /etc/profile.d 的目录,其中包含了系统启动时会运行的 shell 脚本。你可以修改该目录中已有的脚本或添加新脚本。里面的各色脚本只是组织或模块化多种设置的一种方式,这好过将它们一股脑地放进一个大文件中。

由于 shell 通配符扩展的性质以及 . 和 … 目录的存在,grep -l PATH ~/.[^.]* 命令值得注意。

$PATH 中列出的位置会带来安全隐患,尤其作为 root 用户时。如果 root 用户的路径中有一个人皆可写的目录出现在其他典型目录(/bin、/sbin)之前,那么本地用户就可以创建出让 root 执行的文件,从而对系统为所欲为。这也是当前目录(.)不应该出现在 root 用户路径中的原因。

为了避免这个问题:

  • 令 root 用户的路径尽可能简短,绝不要使用相对路径避免在 root 用户的路径中出现人皆可写的目录
  • 考虑在 root 用户执行的 shell 脚本中明确设置路径
  • 对于 root 用户执行的 shell 脚本中用到的实用工具,考虑硬编码其绝对路径
  • 将用户或应用程序目录放在 $PATH 的末尾,只用于非特权用户

5、临时修改$PATH

你想在当前会话期间向 $PATH 中添加(或删除)一个目录。

这个问题的解决方案不止一种。

可以使用 PATH="newdir:$PATH" 或PATH="$PATH:newdir" 将新目录放在前面或后面,不过你得确保该目录不会在 $PATH 中重复出现。

如果需要编辑路径中间的部分,可以通过 echo 命令将路径输出到屏幕,然后使用终端的 kill 和 yank(剪切和粘贴)功能 3 将其复制到新行并进行编辑。你也可以从readline 文档中添加“便于 shell 交互的宏”​(​[m]acrosthat are convenient for shell interaction)​。尤其是:

# 编辑路径
"\C-xp": "PATH=${PATH}\e\C-e\C-a\ef\C-f"
# [...]
# 在当前行编辑变量
"\M-\C-v": "\C-a\C-k$\C-y\M-\C-e\C-a\C-y="

按下 Ctrl-X P,当前行上会显示出 $PATH 的内容,输入任 何变量名称,然后按下 Meta-Ctrl-V,就会显示出该变量的内容,以供编辑。这非常方便。

对于一些简单的情况,你也可以使用下例中的函数(取自 Red Hat Linux 的 /etc/profile,略有改编)​。

# 实例文件:func_pathmunge

# 改编自Red Hat Linux版本

function pathmunge {
    if ! echo $PATH | /bin/egrep -q "(^|:)$1($|:)" ; then
        if [ "$2" = "after" ] ; then
            PATH="$PATH:$1"
        else
            PATH="$1:$PATH"
        fi
    fi
}

egrep 模式 (^|:) 1 ( 1( 1(|:) 用于在 $PATH 字符串中的各个可能位置查找 $1 的值。我们在自己编写的函数func_tweak_path 中选择使用 case 语句,强制在路径的开头和结尾加上了 :。因为用的是 shell 内建命令,所以这种做法在理论上速度会更快,不过 Red Hat 版本要更简洁。我们的版本也很好地演示了 if 命令能够处理退出码,因此第一个 if 可以使用 grep 所设置的退出码,第二个 if则需要使用测试运算符([​])​。

对于需要进行大量错误检查的复杂情况,可以读入并使用下例中给出的更为通用的函数。

# 实例文件:func_tweak_path

#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# 在路径开头或结尾处添加目录(只要该目录尚不存在)
# 不考虑符号链接!
# 返回值:1或者设置好新的$PATH
# 调用方式:add_to_path <directory> (pre|post)
function add_to_path {
    local location=$1
    local directory=$2

    # 确保有可处理的对象
    if [ -z "$location" -o -z "$directory" ]; then
        echo "$0:$FUNCNAME: requires a location and a directory to add" >&2
        echo "e.g. add_to_path pre /bin" >&2
        return 1
    fi

    # 确保不是相对目录
    if [ $(echo $directory | grep '^/') ]; then
        :echo "$0:$FUNCNAME: '$directory' is absolute" >&2
    else
        echo "$0:$FUNCNAME: can't add relative directory '$directory' to \$PATH" >&2
        return 1
    fi

    # 确保要添加的目录确实存在
    if [ -d "$directory" ]; then
        : echo "$0:$FUNCNAME: directory exists" >&2
    else
        echo "$0:$FUNCNAME: '$directory' does not exist--aborting" >&2
        return 1
    fi

    # 确保要添加的目录尚不存在于$PATH之中
    if [ $(contains "$PATH" "$directory") ]; then
        echo "$0:$FUNCNAME: '$directory' already in \$PATH--aborting" >&2
    else
        :echo "$0:$FUNCNAME: adding directory to \$PATH" >&2
    fi

    # 判断要执行的操作
    case $location in
        pre*  ) PATH="$directory:$PATH" ;;
        post* ) PATH="$PATH:$directory" ;;
        *     ) PATH="$PATH:$directory" ;;
    esac

    # 清理新路径并设置$PATH
    PATH=$(clean_path $PATH)

} # 函数add_to_path定义完毕

#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# 从路径中删除目录(如果存在的话)
# 返回值:设置好新的$PATH
# 调用方式:rm_from_path <directory>
function rm_from_path {
    local directory=$1

    # 从$PATH中删除所有的$directory实例
    PATH=${PATH//$directory/}

    # 清理新路径并设置$PATH
    PATH=$(clean_path $PATH)

} # 函数rm_from_path定义完毕


#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# 删除开头/结尾或重复的':',删除重复的目录项
# 返回值:显示“经过清理的”路径
# 调用方式:cleaned_path=$(clean_path $PATH)
function clean_path {
    local path=$1
    local newpath
    local directory

    # 确保有可处理的对象
    [ -z "$path" ] && return 1

    # 删除重复的目录项(如果存在的话)
    for directory in ${path//:/ }; do
        contains "$newpath" "$directory" && newpath="${newpath}:${directory}"
    done

    # 删除开头的':'分隔符
    # 删除结尾的':'分隔符
    # 删除重复的':'分隔符
    newpath=$(echo $newpath | sed 's/^:*//; s/:*$//; s/::/:/g')

    # 返回新路径
    echo $newpath

} # 函数clean_path定义完毕


#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# 判断路径是否包含指定的目录
# 如果目标符合模式,返回1;否则,返回0
# 调用方式:contains $PATH $dir
function contains {
    local pattern=":$1:"
    local target=$2

    # 比较时区分大小写,除非设置过nocasematch选项
    case $pattern in
        *:$target:* ) return 1;;
        *           ) return 0;;
    esac
} # 函数contains定义完毕

用法如下所示:

$ source chpath

$ echo $PATH
/bin:/usr/bin:/usr/local/bin:/usr/bin/X11:/usr/X11R6/bin:/home/jp/bin

$ add_to_path pre foo
-bash:add_to_path: can't add relative directory 'foo' to the $PATH

$ add_to_path post ~/foo
-bash:add_to_path: '/home/jp/foo' does not exist--aborting

$ add_to_path post '~/foo'
-bash:add_to_path: can't add relative directory '~/foo' to the $PATH

$ rm_from_path /home/jp/bin

$ echo $PATH
/bin:/usr/bin:/usr/local/bin:/usr/bin/X11:/usr/X11R6/bin

$ add_to_path /home/jp/bin
-bash:add_to_path: requires a location and a directory to add
e.g. add_to_path pre /bin

$ add_to_path post /home/jp/bin

$ echo $PATH
/bin:/usr/bin:/usr/local/bin:/usr/bin/X11:/usr/X11R6/bin:/home/jp/bin

$ rm_from_path /home/jp/bin

$ add_to_path pre /home/jp/bin

$ echo $PATH
/home/jp/bin:/bin:/usr/bin:/usr/local/bin:/usr/bin/X11:/usr/X11R6/bin

关于这个问题以及例中给出的函数,有 4 个值得注意的地方。

首先,如果尝试在 shell 脚本中修改 $PATH 或其他环境变量,起不到任何效果,因为脚本在子 shell 中运行,脚本结束后,子 shell 也随之终止,修改过的环境变量全部会失效。因此,我们将函数读入当前 shell 环境并在其中运行。

其次,你可能注意到 add_to_path post ~/foo 会返回“does not exist”​,而 add_to_path post’~/foo’ 返回的是“can’t add relative directory”​。原因是,在函数运行之前,shell 会将 ~/foo 扩展成 /home/jp/foo。没考虑到 shell 扩展是一个常见错误。可以用 echo 命令查看shell 到底将什么传给了脚本和函数。

接下来,你可能还会注意到 echo"$0:$FUNCNAME:requires a location and a directory toadd" >&2 这样的代码行。$0:$FUNCNAME 可以方便地识 别出错误消息究竟来自何处。$0 始终保存的是当前程序的名称(本例中为 -bash,其他情况下是脚本或程序的名称)​。加上函数名便于在调试时定位错误。>&2 将输出发送到 STDERR,运行期间产生的用户反馈(尤其是警告或错误信息)都应该出现在这里。

最后,你可以认为这些函数的接口不一致,因为add_to_path 和 remove_from_path 实际上设置了$PATH,而 clean_path 显示的是经过清理的路径,contains 返回真或假。我们在生产环境中并不会这么做,这里只是为了让示例更加有趣,展现不同的处理方式。鉴于这些函数的用途,我们觉得这些接口也说得过去。

6、设置$CDPATH

你希望能够更轻松地在不同位置的多个目录之间进行切换。

恰当地设置 $CDPATH。你的常用目录可能就是那么几个,假设你要花费大量时间来处理 init 的 rc 目录:

/home/jp$ cd rc3.d
bash: cd: rc3.d: No such file or directory

/home/jp$ export CDPATH='.:/etc'

/home/jp$ cd rc3.d
/etc/rc3.d

/etc/rc3.d$ cd rc5.d
/etc/rc5.d

/etc/rc5.d$ cd games
bash: cd: games: No such file or directory

/etc/rc5.d$ export CDPATH='.:/etc:/usr'

/etc/rc5.d$ cd games
/usr/games

/usr/games$

根据 Bash Reference Manual,$CDPATH 是“一个以冒号为分隔符的目录列表,用作内建命令 cd 的搜索路径”​。可以将它看作 cd 的 $PATH。其用法有点微妙,但着实非常方便。

如果 cd 的参数以斜线开头,则用不到 $CDPATH。如果使用了 $CDPATH,则会向 STDOUT 输出新目录的绝对路径,如上面的示例所示。

如果是在 POSIX 模式下运行 bash(例如,/bin/sh 或使用 --posix 选项)​,那可要小心了。Bash Reference Manual 中提到过:

如果使用了 $CDPATH 中的非空目录名,或者第一个参数是 -,而且成功切换了目录,新工作目录的绝对路径会被写入标准输出。

换句话说,几乎每次使用 cd 时都会向 STDOUT 回显新路径,这并非标准行为。

$CDPATH 中常见的目录包括:

  • .:当前目录(可选,因为这是隐含的)
  • ~/:主目录
  • ..:父目录
  • ../..:祖父目录
  • ~/.dirlinks:隐藏目录,只包含指向其他常用目录的符号链接

因此可以得到:

export CDPATH='.:~/:..:../..:~/.dirlinks'

7、当找不到命令时

你希望能够更好地处理找不到命令的情况,或者只是输出更好的错误消息。

将下列函数添加到脚本的起始部分或者 rc 文件中,后者效果更佳:

function command_not_found_handle ()
{
    echo "Sorry. $0: $1 not there."
    return 1
}

在 bash 4.3 及其后续版本中,如果找不到你想要运行的可执行文件,shell 会调用一个特殊的函数command_not_found_handle,你可以根据自己的用途(重新)定义该函数。本例只是让其输出 shell 的名称以及无法找到的命令。

重要的是,函数要能返回非 0 值来表明调用命令失败。脚本的其他部分或脚本的调用者有可能依赖此信息。

有些管理员将函数 command_not_found_handle 的定义放在了系统范围的 bashrc 文件(例如,/etc/profile等)​。在函数内部,查找 /usr/lib 或 /usr/share 下的 Python 脚本 command-not-found(注意是连字符,不是下划线)​。该脚本会查找刚刚调用失败的命令所对应的软件包,看看能否建议安装,以提供缺失的命令。这种做法在某些情况下的确有帮助,但如果只是简单地输错了命令,那这就是添乱了。

8、缩短或修改命令名称

你想将经常用到的那些冗长或复杂的命令变得简短些,或者重新命名难以记忆、不易输入的命令。

不要手动改名或移动可执行文件,因为 Unix 和 Linux 的不少地方都依赖于某些位置上的某些文件;你应该使用别名、函数以及符号链接。

根据 Bash Reference Manual,​“别名允许将简单命令的第一个单词替换成字符串。shell 维护着一系列别名,可以使用内建命令 alias 和 unalias 进行设置和删除”​。这意味着你可以在一个别名中列出多个命令,从而重命名命令或创建宏;例如,alias copy='cp' 或 alias ll.='ls -ld .*'。

别名只能扩展一次,因而得以在不陷入死循环的情况下改变命令的工作方式,比如 alias ls=‘ls -F’。大多数情况下,别名扩展仅检查命令行的第一个单词,而且别名属于严格的文本替换,本身无法使用参数。也就是说,你不能定义别名 alias mkcd='mkdir $1 && cd $1'。

函数有两种用法。首先,它们可以被读入当前的交互式shell 环境,成为常驻内存的脚本。函数占用内存少,由于已经载入内存,运行速度非常快,而且是在当前进程中执行,而非其子进程。其次,函数可以在脚本中作为子程序使用。另外,函数还可以接受参数,如下例所示​。

# 实例文件:func_calc

# 简单的命令行计算器
function calc {
    # 仅适用于整数!--> echo The answer is: $(( $* ))
    # 浮点数
    awk "BEGIN {print \"The answer is: \" $* }";
} # 函数calc定义完毕

对于个人或系统范围的用途而言,使用别名或函数来重命名或调校命令可能更好,但符号链接允许单个命令同时出现在多个位置,这一点非常实用。例如,Linux 系统基本上都是使用 /bin/bash,而其他系统使用的可能是/usr/bin/bash、/usr/local/bin/bash 或者/usr/pkg/bin/bash。虽然有更好的办法处理这个问题​,但符号链接可能是一种通用的解决方式。我们不推荐使用硬链接,因为不大容易看出来它们是否就是你要找的对象,而且硬链接更容易被操作不当的编辑器等破坏。符号链接更加显眼和直观。

在进行别名扩展时,通常只检查命令行的第一个单词。但如果别名值的最后一个字符是空白字符,则接下来的单词也会被检查。这在实践中很少出现什么问题。

由于 bash 中的别名无法使用参数(不同于 csh)​,如果的确需要传递参数,你得使用函数。别名和函数都位于内存中,因此差别不大。

除非设置了 shell 选项 expand_aliases,否则别名不会在非交互式 shell 中扩展。编写脚本的最佳实践要求不使用别名,因为其他系统中未必存在同样的别名。你还需要在脚本中定义函数,或在使用前明确地将其读入​。因此,定义函数的最佳位置是在全局的/etc/bashrc 或本地的~/.bashrc 中。

9、调整shell行为及环境

你希望根据自己的工作方式、物理位置、语言等调整 shell环境。

参见 A.6 节、A.7 节、A.8 节。

有 3 种方法可以调整 shell 环境的方方面面。set 是 POSIX 标准,使用单字母选项。shopt 针对 bash 的 shell 选项。由于历史原因,再加上要与很多第三方应用程序兼容,在用的环境变量数量着实不少。如何调整以及在哪里调整让人倍感困惑。附录 A 中的表格可以帮你理清头绪,由于篇幅过多,这里就不再赘述。

10、用.inputrc调整readline的行为

你想要调整 bash 处理输入的方式,尤其是命令补全。例如,你希望能够忽略大小写。

根据情况,编辑或创建适合的 ~/.inputrc 或 /etc/inputrc文件。有大量的选项可供你根据喜好调整。要想 readline在初始化时使用你所提供的文件,可以设置 $INPUTRC, 例如,INPUTRC=~/.inputrc。要想重新读取文件并应用设置,或修改后进行测试,可以使用 bind -f filename。

我们推荐你研究一下 readline 的文件以及 bind 命令,尤其是 bind -v、bind -l、bind -s、bind -p,最后一个命令涉及的内容颇多,而且晦涩难懂。

有关 readline 的更多配置信息,参见 A.18 节。对于来自其他环境(尤其是 Windows)的用户比较有用的配置是:

# 这是inputrc设置中值得注意的一部分,更长的示例参见16.22节
# 要想重新读取(并应用对该文件做出的改动),可以使用:
# bind -f $SETTINGS/inputrc

# 首先,纳入/etc/inputrc中所有的系统范围绑定和变量赋值
#(如果文件不存在,则静默失败)
$include /etc/inputrc

$if Bash
  # 进行命令补全时忽略大小写
    set completion-ignore-case on
  # 在补全的目录名后添加斜线
    set mark-directories on
  # 如果补全的名称是指向目录的符号链接,在其后添加斜线
    set mark-symlinked-directories on
  # 在补全的名称后添加与ls -F相同的文件类型符号
    set visible-stats on
  # 遍历模棱两可的补全,而不是将其列出
    "\C-i": menu-complete
  # 将铃声设置为能够听到
    set bell-style audible
  # 列出可能的补全结果,而不是响铃
    set show-all-if-ambiguous on

  # 取自readline文档
  # 方便shell交互使用的一些宏
  # 编辑路径
    "\C-xp": "PATH=${PATH}\e\C-e\C-a\ef\C-f"
  # 为输入带引号的单词做准备——插入左双引号和右双引号,
  # 然后将光标移动到左双引号之后
    "\C-x\"": "\"\"\C-b"
  # 插入反斜线(在字符序列和宏中测试反斜线转义)
    "\C-x\\": "\\"
  # 引用当前或前一个单词
    "\C-xq": "\eb\"\ef\""
  # 添加绑定以刷新未绑定的行
    "\C-xr": redraw-current-line
  # 编辑当前行上的变量
    #"\M-\C-v": "\C-a\C-k$\C-y\M-\C-e\C-a\C-y="
    "\C-xe": "\C-a\C-k$\C-y\M-\C-e\C-a\C-y="
$endif

不妨尝试一下这些及其他配置。另外注意,$include 引入了系统配置,但要确保你能够根据需要进行修改。

很多人并没有意识到 GNU readline 库具有多么出色的可定制性,更别提其强大的功能和灵活性了。虽说如此,但并不存在“一劳永逸”的方法。你应该制定适合自己需求和习惯的配置。

注意,第一次调用 readline 时会进行其正常的启动文件处理,包括查看 $INPUTRC,如果该变量未设置,则默认为~/.inputrc。

11、通过添加~/bin来存放个人工具

你有一些要使用的个人工具,但你并非系统的 root 用户,无法将这些工具放入正常的位置(如 /bin 或/usr/local/bin)​,或者出于其他原因,需要将这些工具隔离开。

创建~/bin 目录,将个人工具放入其中并将该目录添加到路径:

PATH="$PATH:~/bin"

你需要在某个 shell 初始化文件(如 ~/.bashrc)中执行上述更改。有些系统已经默认将 $HOME/bin 作为非特权用户账户的最后一个目录,因此最好先检查一下。

作为一名绝对合格的 shell 用户(毕竟你已经买了这本书嘛)​,你肯定创建了不少脚本。使用完整路径名调用脚本实在不方便。通过将脚本汇集到 ~/bin 目录中,至少可以让你的脚本看起来就像普通的 Unix 程序那样。

出于安全考虑,不要将你的 bin 目录放在路径开头。这样很容易覆盖系统命令,如果是无心之举(我们也干过)​,这会很不方便;如果是恶意为之,那可就危险了。

Shell 编程-Bash 并发及并发控制一看就会 今天给伙伴们分享一下Shell 编程-Bash 并发及并发控制,希望看了有所收获。 阅读详情

相关推荐

bash shell脚本编程

文章目录shell编程基础编程语言的分类如何编写shell脚本执行shell脚本(多种方法)在新进程中运行shell脚本检查是否开启了新进程在当前进程中运行 shell 脚本总结 shell编程基础 现在我们使用的操作系统(Windows、Mac os、Android、IOS等)都是带图形化界面的,简单直观,容易上手,对专业用户(程序员、工程师等)和普通用户都非常适用;计算机离不开图形界面。 然...

星光不问赶路人,向知识的苦海前行 1158

Linux中bash环境变量详解

Linux环境变量详解

m0_46829545的博客 5024

个性化 Bash 环境设置指南:自定义 .bashrc 文件

欢迎来到Bash环境自定义的奇妙旅程。对于初学者和经验丰富的IT从业者而言,掌握如何自定义Bash环境不仅能提高工作效率,还能让日常的命令行操作更贴合个人习惯。本章将引导你完成Bash自定义之旅的起始点,介绍必要的基础知识和入门概念。我们将从理解Bash环境的基础开始,逐步过渡到更高级的自定义技巧。首先,我们需要明确什么是Bash。Bash,即“Bourne Again SHell”,是一种广泛应用于Unix系统上的命令行解释器。它允许用户与操作系统直接进行交互,并能够执行各种命令和脚本。

weixin_31659095的博客 2008

Linux的BASH操作环境和设置

管理整个计算机硬件的其实是操作系统的核心 (kernel),我们一般使用者就只能通过 shell 来跟核心沟通,以让核心达到我们所想要达到的工作。

2301_77673652的博客 2393

个人化Bash Shell配置教程与实践

Bash(Bourne Again SHell)是大多数Unix和Linux系统上的默认Shell。作为IT从业者,理解其基本概念与使用方法对于日常操作和系统管理至关重要。Bash不仅仅是一个命令解释器,它还提供了一个丰富的脚本编程环境。本章将带您快速了解Bash Shell的基础知识,包括其历史背景、核心特点以及如何在不同的操作系统中使用Bash。别名是Bash Shell中一种非常实用的功能,它允许用户为长的或者复杂的命令定义一个简短的名称。

weixin_35757191的博客 791

linux bash配置文件

linux bash vim配置文件,不错的配置,可以节省大家时间。

关于 .bashrc

.bashrc文件主要保存个人的一些个性化设置,如命令别名、路径等。也即在同一个服务器上,只对某个用户的个性化设置相关。它是一个隐藏文件,需要使用ls -a来查看。 .bash_history 记录之前输入的命令 .bash_logout 当你退出时执行的命令 .bash_profile 当你登入shell时执行 .bashrc...

qq_40006446的博客 1596

在 NVIDIA Orin (JetPack 6.0) 上配置 PyTorch 2.4 + Torchvision 0.19 的完整避坑指南

本文提供在NVIDIA Jetson Orin设备上,基于JetPack 6.0系统配置PyTorch 2.4与Torchvision 0.19环境的完整指南。通过使用Miniconda环境隔离、安装特定版本PyTorch夜间构建版、编译匹配的Torchvision源码等步骤,解决版本不匹配、CUDA支持等常见问题,确保AI开发环境稳定可用。

weixin_29179311的博客 363

自用 bash配置

# ~/.bashrc: executed by bash(1) for non-login shells. # see /usr/share/doc/bash/examples/startup-files (in the package bash-doc) # for examples # If not running interactively, don't do anything [ -z "$PS1" ] && return # don't put duplicate lines

Running_pink的博客 350

WebVTT中的文本轨道(Text Tracks,TT)到底是什么鬼?

WebVTT,全称是The Web Video Text Tracks Format,意思是网络视频文本轨道格式。那么到底什么是文本轨道(Text Tracks)呢?这篇文章希望一探究竟。

码农1479的博客 1985

Ubuntu22.04上如何用Docker一键部署Ragflow+Ollama(附CUDA配置避坑指南)

本文详细介绍了在Ubuntu22.04系统上使用Docker一键部署Ragflow+Ollama的完整流程,特别提供了CUDA配置的避坑指南。从硬件兼容性检查、驱动安装到容器网络配置,手把手教你搭建本地化大模型环境,解决CUDA驱动冲突等常见问题,助力开发者快速构建AI应用开发平台。

weixin_26875109的博客 284

Shell编程之Csh和Bash的经验总结

文章目录前言1. 命令行参数2. 路径以及文件操作3. 循环获取指定文件夹下的指定类型文件 前言 Shell 编程能提升我们工作效率,但 bash 和 csh 有一定的区别。下面将整理两者不同,以及常用的语法经验。 1. 命令行参数 2. 路径以及文件操作 3. 循环获取指定文件夹下的指定类型文件 ...

guihunkun的博客 4625

PyMiMi实战指南:midas_api配置与连接测试详解

本文详细介绍了PyMiMi库中midas_api的配置与连接测试全流程。从环境准备、API密钥获取,到核心的url_cfg配置函数使用,再到通过test_url进行连接验证,提供了清晰的步骤和代码示例。文章重点解析了配置原理、常见错误排查方法(如401错误、连接超时),并强调了API密钥的安全性管理,帮助用户稳固建立Python与Midas Civil NX之间的自动化通信桥梁。

weixin_29044713的博客 686

Shell编程实例——bash入门

为什么本书要介绍 bash,而不是别的 shell?因为 bash无处不在。它未必是最时髦的,可以说也不是最炫或最厉害的(就算不是,也差不多了)​,更不是唯一一个作为开源软件发布的 shell,但 bash 的大名尽人皆知。究其原因,和历史发展有关。第一批 shell 算得上相当不错的编程工具,但不便于日常使用。C shell 中加入了大量的用户便利功能(例如,可以重复用户输入过的命令)​,但作为编程语言,它又太诡异了。

吴声子夜歌的博客 205

嵌入式SDIO 总线面试题及参考答案

SDIO 的 4 位总线模式是一种提高数据传输效率的工作模式。在传统的 1 位总线模式下,数据只能通过一根数据线(DAT0)进行传输,这限制了数据传输的带宽和速度。而在 4 位总线模式下,DAT0 - DAT3 这 4 根数据线同时用于数据传输,相当于在同一时间内可以传输 4 倍于 1 位模式的数据量,从而显著提高了数据传输的带宽和速度。要通过 CMD6 命令将 SDIO 总线从当前模式切换到 4 位总线模式,需要遵循以下步骤:第一步,主设备需要确保 SDIO 卡支持 4 位总线模式。

大模型大数据攻城狮的专栏 1717

uniapp [全端兼容] - 实现上传本地视频到后端服务器及在线预览播放视频+移除视频+进度条上传,将已选视频上传服务端并可预览视频和删除功能,上传单个或多个视频文件及大文件(H5、小程序、app)

uni-app,h5移动端网页,微信小程序,支付宝小程序,Android安卓,苹果ios,app,nvue,uniapp+uview上传视频并预览,UNI-APP视频上传组件,实现视频文件上传视频回显,上传视频并预览、上传多个视频,实现上传视频功能+预览,上传显示视频功能,上传视频预览移除,批量上传视频,上传超大视频文件,视频上传并预览效果,uniapp上传视频,使用uview上传视频及预览,上传视频和删除视频功能,视频流上传播放功能,上传视频到后端,视频上传与实时预览功能,upload上传组件,视频播放器

🏆 前端领域优质创作者 1万+

linux bash shell.sh编程实例

<br />linux bash shell.sh编程实例(2009-04-25 14:20:05)标签:it分类:原创<br />1.输出<br />#!/bin/bash<br />echo "Please type your number:"<br />read a<br />for ((i=1;i<=a;i++))<br />do<br />for ((p=1;p<=i;p++))<br />do<br />echo -n " $p "<br />done<br />echo<br />done<b

Cloud-Datacenter-Renewable Energy-Big Data-Model 1298

第四节:Vben Admin登录对接后端getUserInfo接口

上一节,我们完成了/api/auth/login接口的创建,通过login接口,我们完成了登录和Token的生成。但是登陆还是报404返回,发现是Vben Admin又请求了一个/api/getUserInfo接口,本节我们就来分析完成这个接口本节,我们完成了getUserInfo接口,完成了登录操作,成功的进入到工作台页面。

cuiwin的专栏 2845

Bash编程实例 一

Shell编程例子 来源: ChinaUnix博客  日期: 2007.04.10 00:07 (共有条评论) 我要评论   Bash编程实例 一 通过学习如何使用 bash 脚本语言编程,将使 Linux 的日常交互更有趣和有生产力,同时还可以利用那些已熟悉和喜爱的标准 UNIX 概念(如管道和重定向)。

shuiyingzi5的专栏 870

导航系统 | 全球四大卫星导航系统(2025)核心能力对比分析

北斗系统通过GEO卫星(80°E、110.5°E、140°E)实现区域增强,其IGSO卫星在亚太地区形成"8"字形轨迹,使该区域可见卫星数量比GPS多4-6颗,显著提升复杂环境下的定位可用性[13]。北斗短报文功能在2025年云南地震救援中发挥关键作用,被困人员通过北斗终端发送120字求救信息,实现"位置+状态"一体化上报,救援响应时间缩短40%[15]。北斗通过三频信号(B1C/B2a/B3)消除电离层延迟误差,在城市峡谷环境下定位连续性达99.98%,优于GPS的99.95%[5]。

尘世冰封的专栏 2611

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

Bash反弹shell

机器名称机器IP攻击机器实验靶机Python由荷兰数学和计算机科学研究学会的吉多·范罗苏姆于1990年代初设计,作为一门叫做ABC语 言的替代品。Python提供了高效的高级数据结构,还能简单有效地面向对象编程。Python语法和动 态类型,以及解释型语言的本质,使它成为多数平台上写脚本和快速开发应用的编程语言,随着版本 的不断更新和语言新功能的添加,逐渐被用于独立的、大型项目的开发。python反弹shell介绍python2s.connect(("攻击机器IP",端口));机器名称。

qq_64177395的博客 1458

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

Bash和Shell

Bash和Shell同为命令行解释器,二者的区别。

m0_64196863的博客 1160

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

linux中的shell与bash的关系

Linux中的Shell与Bash的关系**Linux中"Shell"与"Bash"的关系**1、认识Shell2、认识Bash3、Shell与Bash关系 Linux中"Shell"与"Bash"的关系 此文属于我在学习Linux中的学习记录,便于回头查找相应文档使用,大多数解释都为其它网站引用,也用来分享给大家做个参考, 1、认识Shell 在计算机科学中,Shell俗称壳(用来区别于核),是指“为使用者提供操作界面”的软件(命令解析器)。它类似于DOS下的command.com和后来的cmd.exe。

skateboy01的博客 1214

Shell 和 Bash 是一家人,但真的不一样: 深入理解 Bash 和 Shell 的区别与联系

你是否曾经在终端里敲过命令,却从未想过背后是谁在默默执行你的指令?今天,我们就来聊聊命令行世界的两位“大佬”:Shell 和 Bash。它们看起来很像,但其实各有各的“绝活”!

大葱的田地🌱 1985

bash shell 脚本编程

变量的生效范围等标准划分变量类型普通变量:生效范围为当前shell进程;对当前shell之外的其它shell进程,包括当前shell的子shell 进程均无效环境变量:生效范围为当前shell进程及其子进程本地变量:生效范围为当前shell进程中某代码片断,通常指函数set。

qq_59349464的博客 1263

Bash Shell 的展开与补全机制

Bash 命令行处理遵循严格的展开顺序:首先执行大括号展开,随后同时处理波浪号、变量、算术和命令替换,再进行单词分割和路径名展开,最后移除引号。关键机制包括历史展开(如 !! 和 !$)、波浪号展开(~ 主目录引用)以及 Tab 补全功能,后者支持可编程补全规则。实用技巧如 cd - 切换目录、Alt+. 快速引用参数能显著提升效率。掌握这些展开顺序和交互功能可以优化命令行操作,减少重复输入。

vortex5的博客 1386
上一篇: Shell编程实例——高级脚本编程(二)
下一篇: Shell编程实例——bash的配置与自定义(二)
吴声子夜歌
博客等级 码龄9年 2687粉丝 2262原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值