shell中单引号双引号和`` 的区别
name="hello"
echo name
echo "$name"
echo '$name'
echo $name
猜猜输出结果是什么,其实是
在shell中,双引号下的变量能被解析,但是单引号下的变量不能解析
此外,``包裹的命令返回的结果,也可以存储在变量中
list=`date`
echo $list
shell中source xx.sh
,bash xx.sh
, ./xx.sh
的区别
这三个命令都涉及在Shell中执行脚本文件,但它们之间有一些区别。让我为您解释一下:
source xx.sh
用于在当前的Shell环境中运行指定的脚本文件(通常是一个以.sh为扩展名的Shell脚本)。执行后,脚本中的命令会直接在当前的Shell进程中执行,而不会创建新的子进程。这意味着脚本中的变量赋值、函数定义等对当前Shell环境是可见和影响的。
例如:
source myscript.sh
bash xx.sh
这个命令用于在一个新的bash子进程中执行指定的脚本文件。它会创建一个新的bash Shell环境,然后在该环境中执行脚本。在这种情况下,脚本中的变量赋值和其他操作只会在子进程的环境中生效,对于调用该命令的父Shell环境没有影响。
例如:
bash myscript.sh
./xx.sh
这个命令用于运行当前目录下的可执行脚本文件。您需要确保脚本文件拥有执行权限(使用 chmod +x xx.sh 添加执行权限)。这种方式也会创建一个新的子进程来运行脚本,并且与使用 bash xx.sh 类似,脚本中的变量赋值和其他操作只会在子进程中生效。
例如:
./myscript.sh
综上所述,选择何种方式取决于您希望在哪个环境中运行脚本以及脚本中的操作是否需要影响当前的Shell环境。如果您想要修改当前的Shell环境,通常会使用 source 或 . 命令,而如果只是需要执行脚本而不影响当前环境,可以使用 bash 或 ./ 命令。
环境变量
-
设置临时环境变量:
在当前Shell会话中,您可以使用
export
命令设置临时环境变量。假设您希望将一个临时变量MY_TEMP_VAR
设置为Hello, World!
:export MY_TEMP_VAR="Hello, World!" echo $MY_TEMP_VAR
这将在当前会话中输出
Hello, World!
。 -
永久设置用户级环境变量:
假设您希望设置一个永久的环境变量,使其对特定用户的所有会话都生效。您可以将变量添加到用户的
~/.bashrc
文件中。打开该文件并添加以下内容:export MY_USER_VAR="This is my user-level variable"
然后使用以下命令使更改生效:
source ~/.bashrc
现在,
$MY_USER_VAR
将在您登录时的每个会话中都可用。 -
永久设置全局环境变量:
假设您想要设置一个在系统范围内对所有用户和会话都生效的环境变量。您可以创建一个新的文件,例如
/etc/profile.d/my_global_vars.sh
,并在其中添加以下内容:export GLOBAL_VAR="This is a global variable"
您不需要手动运行
source
命令,因为/etc/profile.d/
中的文件会在系统启动时自动加载。 -
检查环境变量:
使用
set
、env
和declare
命令来检查环境变量。例如:# 显示所有变量 set # 显示全局变量 env # 与set类似,显示所有变量 declare
通过这些命令,您可以查看当前会话中设置的各种变量。
-
使用
export
命令显示和设置环境变量值:使用
export
命令显示和设置环境变量的值。例如:# 显示已导出的所有环境变量 export # 设置新的环境变量 export NEW_VAR="New variable value" # 更新已有的环境变量 export MY_TEMP_VAR="Updated value"
这些命令允许您查看和操作当前会话中的环境变量。
撤销环境变量
要撤销环境变量,您可以使用unset
命令。这个命令允许您从当前Shell会话中删除一个已经存在的环境变量。请注意,使用unset
命令只会在当前会话中删除变量,不会影响到其他会话或持久性设置。
以下是如何使用unset
命令来撤销环境变量的示例:
-
撤销临时环境变量:
如果您之前使用
export
命令设置了一个临时环境变量,您可以使用unset
命令将其删除。例如,假设您设置了临时变量MY_TEMP_VAR
,现在想要将其删除:export MY_TEMP_VAR="Hello, World!" echo $MY_TEMP_VAR # 输出: Hello, World! unset MY_TEMP_VAR echo $MY_TEMP_VAR # 输出: 空
在这个例子中,
unset
命令删除了之前设置的临时变量。 -
永久删除用户级环境变量:
要永久删除用户级环境变量,您需要编辑用户的配置文件(如
~/.bashrc
)并删除相应的行。例如,假设您在~/.bashrc
中设置了一个变量MY_USER_VAR
:export MY_USER_VAR="This is my user-level variable"
您可以通过编辑文件并删除该行来撤销变量的设置,然后使用
source
命令使更改生效。 -
删除全局环境变量:
要删除全局环境变量,您可以编辑全局配置文件(如
/etc/profile.d/my_global_vars.sh
)并删除相应的设置行。删除行后,全局变量将在系统启动时不再生效。
只读变量
Shell 中的只读变量是一种特殊类型的变量,其值一旦设置后就不能再被修改。这可以用来确保某些重要的配置信息或环境变量不会被意外地更改。只读变量在脚本编写和系统管理中非常有用,可以帮助避免潜在的错误和安全问题。
在大多数Shell(如Bash)中,您可以使用 readonly
关键字来定义只读变量。以下是一些有关只读变量的重要信息:
-
定义只读变量:
使用
readonly
关键字可以将一个变量声明为只读。一旦变量被设置为只读,任何尝试修改其值的操作都会被拒绝。readonly MY_READONLY_VAR="This variable is read-only"
-
尝试修改只读变量:
如果您尝试修改一个只读变量,Shell 将会报错,并且不会允许修改。
MY_READONLY_VAR="Trying to change the value" # 这里会报错
-
只读变量的应用:
只读变量在以下情况下很有用:
-
保护配置信息:您可以将脚本中使用的配置信息定义为只读变量,确保脚本不会在运行时意外修改配置。
-
环境变量保护:一些重要的环境变量,如
PATH
,可以声明为只读,以防止被恶意修改,从而影响系统的正常运行。 -
脚本参数:如果脚本需要接收参数,您可以将这些参数定义为只读变量,以防止在脚本内部意外更改。
-
-
取消只读设置:
要取消变量的只读设置,您可以使用
unset
命令将变量从只读状态中解除。readonly MY_READONLY_VAR unset MY_READONLY_VAR # 这将取消只读设置
Shell配置加载顺序
只读变量可以在编写安全和稳定的脚本中起到很好的作用。通过将关键信息声明为只读,可以减少潜在的错误和安全漏洞,确保脚本和系统的可靠性。
在Linux和Unix-like系统中,Shell 的配置文件会在启动时按照一定的顺序加载,以设置初始的环境变量、别名、函数等。不同的Shell有不同的配置文件和加载顺序。以下是一些常见的Shell配置文件和它们的加载顺序:
-
Bash Shell:
/etc/profile
:系统级别的配置文件,对所有用户有效。/etc/bash.bashrc
:系统级别的配置文件,用于定义全局别名和函数。~/.bash_profile
:用户个人配置文件,用于用户登录时执行的命令。~/.bashrc
:用户个人配置文件,用于定义用户特定的别名、函数和设置。/etc/profile.d/
目录:通常,系统管理员可以将特定的配置文件放在这个目录下,这些文件会在用户登录时加载。
加载顺序:
/etc/profile
/etc/bash.bashrc
~/.bash_profile
或~/.bash_login
或~/.profile
(根据存在性选择其中一个)~/.bashrc
-
Zsh Shell:
/etc/zsh/zshenv
:系统级别的配置文件,在所有用户之前加载。~/.zshenv
:用户个人配置文件,用于定义用户特定的环境变量。/etc/zsh/zprofile
:系统级别的配置文件,用于用户登录时执行的命令。~/.zprofile
:用户个人配置文件,用于用户登录时执行的命令。/etc/zsh/zshrc
:系统级别的配置文件,用于定义全局别名和函数。~/.zshrc
:用户个人配置文件,用于定义用户特定的别名、函数和设置。/etc/zsh/zlogin
:系统级别的配置文件,在用户登录时执行。~/.zlogin
:用户个人配置文件,在用户登录时执行。~/.zlogout
:用户个人配置文件,在用户退出登录时执行。
加载顺序:
/etc/zsh/zshenv
~/.zshenv
/etc/zsh/zprofile
~/.zprofile
/etc/zsh/zshrc
~/.zshrc
/etc/zsh/zlogin
~/.zlogin
~/.zlogout
不同Shell的配置加载顺序可能会略有不同,但总体思路是在启动时加载系统级别和用户级别的配置文件,以设置合适的环境变量、别名和函数,确保Shell会话以期望的方式运行。
特殊变量
在Shell编程中,有一些被称为特殊变量(Special Variables)的预定义变量,它们提供了有关脚本和Shell环境的重要信息。这些特殊变量在不同的Shell中可能有所不同,下面是一些常见的特殊变量以及它们的含义:
-
$0
:表示当前脚本或命令的名称。通常用于获取脚本自身的名称,以用于日志记录或报错信息。 -
$1
,$2
, …:表示脚本或函数的参数。$1
表示第一个参数,$2
表示第二个参数,以此类推。 -
$#
:表示传递给脚本或函数的参数个数。 -
$@
:表示所有传递给脚本或函数的参数,每个参数都被视为一个独立的参数。 -
$*
:类似于$@
,表示所有传递给脚本或函数的参数,但将它们作为单个字符串处理。 -
$?
:表示上一个命令的退出状态码(返回值)。通常用于检查上一个命令是否成功执行(退出状态码为0)。 -
$$
:表示当前脚本或命令的进程ID(PID)。 -
$!
:表示最后一个在后台运行的进程的PID。 -
$USER
(在Bash中):表示当前用户的用户名。 -
$HOME
(在Bash中):表示当前用户的主目录路径。 -
$SHELL
(在Bash中):表示当前用户所使用的Shell的路径。 -
$PWD
(在Bash中):表示当前工作目录的路径。 -
$OLDPWD
(在Bash中):表示上一个工作目录的路径。 -
$IFS
(在Bash中):表示内部字段分隔符,用于定义以空格、制表符等分隔符分割的字符串中的字段。 -
$_
:代表上一个命令的最后一个参数。在交互式Shell会话中,它通常用于获取上一个命令的参数,以便在后续命令中使用。
在Shell编程中,$*
和 $@
都表示传递给脚本或函数的所有参数,但在处理参数时有一些微妙的区别。
-
$*
:将所有参数作为单个字符串处理。参数之间由第一个字符的值所代表的IFS(Internal Field Separator,内部字段分隔符)分隔。通常,默认的IFS是空格。这意味着$*
会将所有参数合并成一个单一的字符串。 -
$@
:将每个参数视为独立的项,每个参数保留其原始形式,不会合并成单一的字符串。这使得$@
在处理参数时更灵活,不受IFS的影响。
下面是一个示例,展示了$*
和 $@
在处理参数时的区别:
#!/bin/bash
echo "Using \$*:"
for arg in $*; do
echo $arg
done
echo -e "\nUsing \$@:"
for arg in $@; do
echo $arg
done
假设将上述代码保存为args_example.sh
,然后运行如下命令:
bash args_example.sh arg1 arg2 "arg3 with spaces"
输出会是:
Using $*:
arg1
arg2
arg3
with
spaces
Using $@:
arg1
arg2
arg3 with spaces
可以看到,在$*
中,参数被空格分隔,并且"arg3 with spaces"被分割成了多个部分。而在$@
中,参数保留了它们的原始形式,不受空格影响。这就是它们之间的区别。通常情况下,建议在大多数情况下使用$@
,因为它更符合通常对参数的期望处理方式。
$_
:代表上一个命令的最后一个参数。在交互式Shell会话中,它通常用于获取上一个命令的参数,以便在后续命令中使用。
例如,假设您在Shell中执行以下命令:
$ echo "Hello, World!"
然后,您可以使用$_
来引用上一个命令的最后一个参数,如下所示:
$ echo "The last command was: $_"
The last command was: Hello, World!
在这个例子中,$_
会被替换为上一个命令的参数,即"Hello, World!"。
请注意,$_
只包含上一个命令的最后一个参数,而不是整个参数列表。如果要获取整个参数列表,您应该使用$@
或$*
。
bash一些基础的内置命令
下面是一些基础的bash内置命令的简要说明:
-
echo
:用于在终端输出文本或变量的值。 -
eval
:用于将参数作为命令执行,并将结果返回。 -
exec
:用于替换当前进程,并执行指定的命令。一旦执行了exec
命令,原始进程将被替换,不会返回到原来的脚本。 -
export
:用于将变量导出为环境变量,使其在当前Shell会话及其子进程中可见。 -
read
:用于从标准输入读取用户的输入,并将其存储到变量中。 -
shift
:用于向左移动位置参数(命令行参数),使得$2
变为$1
,$3
变为$2
,以此类推。这在处理多个命令行参数时很有用。
echo实战
echo
命令用于在终端输出文本或变量的值。下面是一些常用的 echo
命令选项:
-
-n
:不换行输出。默认情况下,echo
输出完文本后会自动换行,使用-n
选项可以禁止换行,使输出保持在同一行。 -
-e
:解析字符串中的特殊符号。使用-e
选项可以让echo
解析字符串中的特殊字符,例如\n
表示换行符,\t
表示制表符等。这样可以在输出中插入特殊字符。 -
\
:表示转义字符。在字符串中使用反斜杠\
可以转义特殊字符,例如\"
表示双引号,\\
表示反斜杠本身。
例如,下面是一些示例:
echo "Hello, World!" # 输出:Hello, World!
echo -n "Hello, " # 输出:Hello,
echo "World!" # 输出:World!
echo -e "Line 1\nLine 2\tTabbed" # 输出:
# Line 1
# Line 2 Tabbed
echo "This is a quote: \"To be or not to be\"" # 输出:This is a quote: "To be or not to be"
read实战
read
命令用于从标准输入(通常是终端)读取用户的输入,并将输入的内容存储到一个或多个变量中。下面是 read
命令的基本用法:
read [options] variable1 variable2 ...
-
options
:可以使用一些选项来控制read
命令的行为,例如设置超时时间、指定分隔符等。常用的选项包括:-
-p <prompt>
:显示一个提示符,提示用户输入。 -
-s
:静默模式,用户输入的内容不会显示在终端上。
-
-
variable1 variable2 ...
:指定一个或多个变量,用于存储用户输入的内容。输入的内容会按照空格或指定的分隔符进行分割,并依次存储到每个变量中。
下面是一个简单的示例,演示了如何使用 read
命令读取用户的输入并存储到变量中:
read -p "请输入您的姓名: " name
echo "您好,$name!欢迎使用本系统。"
在运行上述代码时,会提示用户输入姓名,用户输入的内容将存储到 name
变量中,并通过 echo
命令输出欢迎消息。
-s一般用来输入密码
read -s -p "请输入密码: " password
echo "您输入的密码是: $password"
上述代码会不断提示用户输入数字,直到用户输入字母 “q” 为止。
eval实战
command="ls ../ -a"
eval $command
exec实战
exec date
在执行完这个命令后会马上执行exit,退出当前用户