Shell脚本里那些让你抓狂的小细节,你真的全都搞懂了吗?

[[ $var == “hello” ]]和[ $var = “hello” ]到底谁是谁?

别急着回答,这个问题能问倒一半的Shell初学者。

先说那个方括号[ ],它实则是个命令!没错,[是一个内置命令,和ls、cd没什么本质区别。所以[ $var = “hello” ]实际上是在执行一个测试命令,检查变量是否等于字符串。注意这里只能用单个等号=,而且两边必须有空格。

Shell脚本里那些让你抓狂的小细节,你真的全都搞懂了吗?

双括号[[ ]]就高级多了,它是Bash的关键字,不是命令。这意味着它有自己的语法规则,不会像命令那样被解析。在[[ ]]里面,你可以用==、!=这些更直观的操作符,还能用正则表达式匹配!

最要命的是引号处理——[ ]对空变量特别敏感。试试这个:

var=""
[ $var = "hello" ]

报错!由于展开后变成了[ = “hello” ]

[[ $var == “hello” ]]

正常执行,返回false


**空变量在`[ ]`里会直接导致语法错误**,但在`[[ ]]`里完全没问题。这就是为什么现代脚本都推荐用双括号,安全多了。

$?这个神秘符号,居然能告知你命令成功与否?

每次执行命令,系统都会悄悄记录它的“退出状态”。0表明成功,非0表明失败。$?就是读取这个状态值的密码。

Shell脚本里那些让你抓狂的小细节,你真的全都搞懂了吗?

别小看这个功能,它在自动化脚本里简直是救命稻草。列如你要检测服务器是否在线:

ping -c 1 google.com > /dev/null 2>&1

if [ $? -eq 0 ]; then
    echo "网络畅通!"
else
    echo "糟糕,连不上网..."
fi

那个> /dev/null 2>&1是把所有输出都扔进黑洞,我们只关心成功与否。$?必定要立即使用,由于它只保存最近一条命令的状态。你要是中间插个echo,状态就被覆盖了。

更高级的用法是直接放在条件判断里:

if ping -c 1 google.com &> /dev/null; then
    echo "一切正常"
fi

这样连$?都不用写了,简洁又直观。

set -u:让你的脚本不再容忍未定义变量

写脚本最怕什么?变量名打错还浑然不知!set -u就是治这个毛病的良药。

开启这个选项后,任何使用未定义变量的行为都会立即报错。列如:

!/bin/bash

set -u

name=”张三” echo “你好,$naem”

这里故意打错变量名


运行这个脚本,你会看到清晰的错误信息:“naem: 未绑定的变量”。没有`set -u`的话,脚本会默默输出“你好,”,留给你一脸懵逼。



**生产环境的脚本都应该加上`set -u`**,它能帮你提前发现许多低级错误。配合`set -e`(遇到错误立即退出)和`set -o pipefail`(管道中任意命令失败就失败),你的脚本健壮性会提升好几个档次。

不过要注意,检查变量是否为空要用正确姿势:

```bash

错误方式

if [ -z “$undefined_var” ]; then

触发set -u报错

echo “变量为空” fi

正确方式

if [ -z “${undefined_var:-}” ]; then

使用默认值语法

echo “变量为空或未定义” fi

遍历.sh文件,原来有这么多门道

“找出所有.sh文件”——听起来简单对吧?但新手常犯的错能让你笑出声。

最天真的写法:

for file in *.sh; do
    echo "$file"
done

问题来了:如果当前目录没有.sh文件,*.sh不会被展开,而是直接把“.sh”当作文件名!循环会执行一次,输出“.sh”。

Shell脚本里那些让你抓狂的小细节,你真的全都搞懂了吗?

安全一点的写法是用find:

find . -name "*.sh" -type f | while read file; do
    echo "找到脚本:$file"
done

但这里又有坑:管道创建的while循环是在子Shell里执行的,循环里修改的变量在外部无效。试试这个:

count=0
find . -name "*.sh" | while read file; do
    count=$((count + 1))
done
echo "找到 $count 个文件"

输出0!由于count在子Shell里被修改


解决方法是用进程替换:

```bash
while read file; do

处理文件

done < <(find . -name “*.sh” -type f)


或者更现代的写法,用`globstar`选项(Bash 4.0+):

```bash
shopt -s globstar
for file in **/*.sh; do
    [[ -f "$file" ]] && echo "$file"
done

1到100求和,Shell居然有五种写法?

你以为求和只能用循环?太天真了!

最经典的for循环

sum=0
for ((i=1; i<=100; i++)); do
    sum=$((sum + i))
done
echo "总和:$sum"

seq命令一行搞定

echo $(seq 1 100 | tr '
' '+' | sed 's/+$/
/') | bc

这个魔法一样的一行命令,实则是生成了“1+2+3+…+100”的表达式,然后交给bc计算器。

用awk更简洁

seq 1 100 | awk '{sum+=$1} END{print sum}'

甚至可以用数学公式

n=100
sum=$((n * (n + 1) / 2))
echo "高斯算法:$sum"

Shell脚本里那些让你抓狂的小细节,你真的全都搞懂了吗?

最骚的是用Bash的brace expansion

echo {1..100} | tr ' ' '+' | bc

不过要注意,大括号展开在数字太多时可能超出命令行长度限制。选择哪种方法取决于具体场景:小数字用循环,大数字用公式或awk,炫技时用那一行魔法命令。

既要看输出又要存日志,鱼和熊掌能兼得吗?

当然能!tee命令就是为这个而生的。

./some_script.sh | tee logfile.txt

这样屏幕上能看到实时输出,同时所有内容都保存到logfile.txt。但等等,错误输出怎么办?默认只捕获标准输出。

完整版应该是:

./some_script.sh 2>&1 | tee logfile.txt

2>&1把错误输出重定向到标准输出,这样错误信息也能被tee捕获。

更实用的是同时记录到日志文件:

./some_script.sh 2>&1 | tee -a app.log

-a参数表明追加,不会覆盖原有日志。生产环境常用这种模式,既方便调试,又保留历史记录。

如果你还想把输出同时发给多个地方:

./some_script.sh 2>&1 | tee >(grep ERROR > errors.log) >(grep WARN > warnings.log) > all.log

这个命令把输出同时送到错误日志、警告日志和完整日志,一箭三雕。

$0、$1、$@、$#:脚本参数的四大护法

写脚本总要处理参数吧?这几个特殊变量就是你的武器库。

$0:脚本自己的名字。但这里有个坑——它可能是相对路径、绝对路径,或者就是脚本名。想获取纯文件名?用basename “$0″。

$1、$2…:第1、2…个参数。必定要用双引号括起来,列如”$1″,否则带空格的参数会出问题。

$#:参数个数。判断是否有参数时别用`[ $

-gt 0 ]`,万一`set -u`开着会报错。用`[ $# -gt 0 ]`或者`(( $# > 0 ))`。

Shell脚本里那些让你抓狂的小细节,你真的全都搞懂了吗?

$@和$*的区别:这是经典面试题。不加引号时两者一样,加引号后”$@”是每个参数单独引号包围,”$*”是所有参数合并成一个字符串。

看例子:

脚本 test.sh:
echo "用$@:"
for arg in "$@"; do
    echo "[$arg]"
done

echo "用$*:"
for arg in "$*"; do
    echo "[$arg]"
done

运行:./test.sh "a b" c
输出:
用$@:
[a b]
[c]
用$*:
[a b c]

处理参数时永远用”$@”,这是唯一能正确处理所有情况的方式。

判断Shell脚本可执行?别只看x标志

你以为-x判断就够了?太年轻!

if [[ -x "$file" ]]; then
    echo "文件可执行"
fi

这只能判断文件有执行权限。但有权限不必定是Shell脚本,可能是二进制程序、Python脚本,甚至是个文本文件被人误加了x权限。

真正的Shell脚本判断应该是:

if [[ -x "$file" ]] && [[ -f "$file" ]] && head -n 1 "$file" | grep -q "^#!.*bash|sh"; then
    echo "这是一个可执行的Shell脚本"
fi

head -n 1读取第一行,检查是否有shebang(#!)。注意有些脚本可能写#!/usr/bin/env bash,所以模式要灵活些。

更严格的话还要检查文件类型:

if file "$file" | grep -q "shell script"; then
    echo "file命令也认为是Shell脚本"
fi

实际开发中,综合使用多种判断最可靠。特别是处理用户上传的文件时,安全检查必须做足。

awk和cut:文本处理的双子星,谁更胜一筹?

awk '{print $1}'和cut -d' ' -f1看起来干一样的事,但细节决定成败。

cut是简单的列切割工具,按固定分隔符工作。空格分隔?没问题。但如果是多个连续空格呢?

echo "a   b   c" | cut -d' ' -f1

输出a

echo “a b c” | cut -d' ' -f2

输出空!由于-d' '只认单个空格


**awk默认用任意空白字符(空格、制表符)分隔**,而且会压缩连续的空白:

```bash
echo "a   b   c" | awk '{print $1}'

输出a

echo “a b c” | awk '{print $2}'

输出b,正确处理多个空格



awk更强劲的地方在于能处理复杂情况:

```bash

打印最后一列

awk '{print $NF}'

打印除了第一列的所有列

awk '{$1=””; print substr($0,2)}'

条件打印:只打印第二列大于10的行

awk '$2 > 10 {print $1, $2}'


**简单固定格式用cut,复杂处理用awk**。还有一个常用组合:`awk -F','`指定逗号分隔,处理CSV文件比cut方便多了。

sed替换全文件,这些陷阱你必定要知道

sed 's/old/new/g' file——教科书都这么写,但实际用起来坑不少。

第一个坑:原文件没被修改!sed默认输出到屏幕,要加-i参数才能原地修改:

sed -i 's/old/new/g' file.txt

第二个坑:特殊字符。如果old或new包含斜杠/怎么办?

错误

sed 's/path/to/file/path/to/new/g'

斜杠太多,解析错误

正确:用其他分隔符

sed 's|path/to/file|path/to/new|g' sed 's#old#new#g'

用#号也行


**第三个坑:贪婪匹配**:

```bash
echo "old old thing" | sed 's/old.*thing/NEW/g'

整个字符串被替换



**第四个坑:换行符**。sed默认按行处理,跨行匹配要特殊处理:

```bash
sed ':a;N;$!ba;s/old
old/NEW/g' file.txt

更安全的做法是先用备份:

sed -i.bak 's/old/new/g' file.txt

生成file.txt.bak备份


对于大文件,sed比一些图形编辑器快得多。**掌握sed的正则表达式**,你就能批量处理成千上万个文件,效率提升不是一点半点。

#!/bin/bash和#!/bin/sh:一字之差,天壤之别

脚本第一行这个shebang,写错的人太多了。

#!/bin/sh指向系统的默认Shell,可能是Bash,也可能是dash、ksh等其他Shell。在Ubuntu上,/bin/sh默认是dash,一个更精简、更严格的Shell。

#!/bin/bash明确要求用Bash执行,能用上Bash的所有扩展功能。

区别有多大?试试这个脚本:

!/bin/sh

array=(1 2 3) echo ${array[1]}

`#!/bin/sh`(实际是dash)运行会报错:“Syntax error: "(" unexpected”。由于**数组语法是Bash的扩展**,标准Shell不支持。

其他Bash特有的功能:

双括号`[[ ]]`

进程替换`<(command)`

大括号展开`{1..10}`

正则表达式匹配`=~`

**安全提议**:如果你用了任何Bash特有功能,就必须写`#!/bin/bash`。如果想让脚本更通用,限制自己只用POSIX标准语法,然后写`#!/bin/sh`。

检查脚本兼容性可以用:

```bash
bash -n script.sh

检查语法

dash -n script.sh

用dash检查

source命令:为什么它能“污染”当前环境?

最后这个问题触及Shell的本质。

当你直接运行脚本时,Shell会创建一个子进程(子Shell)。脚本里的一切操作都在这个沙箱里进行:变量赋值、函数定义、目录切换…脚本结束,沙箱销毁,一切恢复原样。

但source script.sh(或. script.sh)完全不同。它说:别创建子进程了,直接在当前Shell里执行这些命令

这意味着:

脚本设置的变量在当前Shell中可用

脚本改变目录,你的当前目录真的会变

脚本定义的函数,你可以直接调用

脚本设置的alias,你也能用

Shell脚本里那些让你抓狂的小细节,你真的全都搞懂了吗?

这既是强劲功能,也是危险来源。不小心source了一个有exit的脚本?你的终端直接关闭了!

常见用途:

加载配置:. ~/.bashrc

设置环境变量:许多软件安装脚本要你source一个setup文件

定义常用函数:把常用函数放在一个文件里,需要时source

最佳实践:除非明确需要影响当前环境,否则不要用source。特别是运行别人写的脚本前,先看一眼内容,别莫名其妙改了你的环境。

一个保护技巧:

在子Shell中source,避免污染

( source some_script.sh

这里可以检查脚本效果

)

回到这里时,some_script.sh的影响已经消失


Shell脚本就像一把瑞士军刀,小巧但功能丰富。每个细节背后都有设计逻辑,理解这些,你就能写出既健壮又优雅的脚本。别停留在“能用就行”,深入一点,你会发现另一个世界。

Shell脚本里的这些坑,你真的全都踩过吗?看完这篇就够了!

你是不是常常写Shell脚本,却总觉得有些地方不对劲?那些看似简单的语法背后,藏着多少不为人知的秘密?今天我们就来揭开这些谜底,让你彻底告别脚本bug!

Shell脚本里那些让你抓狂的小细节,你真的全都搞懂了吗?

[[ $var == “hello” ]]和[ $var = “hello” ]到底有什么区别?

这个问题看起来简单,却让无数人栽了跟头。你以为它们是一样的?大错特错!

先说那个方括号[ ],它是传统的test命令。没错,你没看错,[实则是一个命令!它需要遵循严格的空格规则。如果你写成[ $var = “hello” ],当$var为空时,这个命令就变成了[ = “hello” ],直接语法错误!

双括号[[ ]]就机智多了,它是Bash的内置关键字,不会拆分词。即使$var是空的,[[ $var == “hello” ]]也能正确处理,不会报错。而且[[ ]]支持模式匹配,列如[[ $file == *.txt ]],这在[ ]里是行不通的。

还有一个重大区别:[[ ]]里的==和=是完全一样的,都是字符串比较。但在[ ]里,=用于字符串比较,==在某些Shell里可能不被支持。

简单来说,能用[[ ]]就别用[ ],除非你要思考跨Shell兼容性。

$?的妙用:如何优雅地检测命令执行状态?

$?这个神奇的小东西,记录着上一条命令的退出状态。0表明成功,非0表明失败。但你知道怎么用好它吗?

看看这个常见的ping检测脚本:

!/bin/bash

ping -c 1 baidu.com > /dev/null 2>&1

if [ $? -eq 0 ]; then echo “网络连接正常!” else echo “网络连接失败!” fi


**但这样写实则不够优雅**!更好的做法是直接判断命令:

```bash
if ping -c 1 baidu.com &> /dev/null; then
    echo "网络畅通无阻!"
else
    echo "哎呀,网络好像断了..."
fi

看到区别了吗?直接在if里执行命令,让代码更简洁清晰。$?的真正价值在于需要具体错误码的时候,列如:

grep "pattern" file.txt
case $? in
    0) echo "找到了!" ;;
    1) echo "没找到..." ;;
    2) echo "文件打不开!" ;;
    *) echo "发生了未知错误" ;;
esac

Shell脚本里那些让你抓狂的小细节,你真的全都搞懂了吗?

set -u:让你的脚本告别”未定义变量”的噩梦!

你有没有遇到过这样的错误:line 10: var: unbound variable?这就是未定义变量惹的祸!

set -u就是来解决这个问题的。加上这行魔法咒语,脚本里任何未定义的变量都会立即报错,而不是默默地使用空值。

看看这个例子:

!/bin/bash

不加set -u

name=$USERNAME

假设USERNAME没定义

echo “你好,$name!”

运行结果:你好,!

空荡荡的,奇怪但不会报错


目前加上`set -u`:

```bash

!/bin/bash

set -u

name=$USERNAME

这里会立即报错!

echo “你好,$name!”

运行结果:line 3: USERNAME: unbound variable

立即发现问题所在!


**这个特性在调试时特别有用**。它能帮你快速定位那些由于拼写错误导致的变量未定义问题。想象一下,你写的是`$file_path`,不小心打成了`$file_paht`,没有`set -u`的话,这个bug可能隐藏很久都发现不了!

有时候你的确   需要变量为空,这时候可以这样写:`${var:-默认值}`,给变量一个默认值。

遍历.sh文件的几种姿势,你都会吗?

遍历文件是Shell脚本的日常操作,但方法可不止一种!

最直接的方法:

for file in *.sh; do
    echo "处理文件:$file"

你的处理逻辑

done


但这个方法有个问题:如果当前目录没有.sh文件,`*.sh`不会被扩展,`file`的值就是字面量的"*.sh"。这时候需要加个判断:

```bash
for file in *.sh; do
    if [ -f "$file" ]; then
        echo "找到脚本:$file"
    fi
done

更安全的方法是用find:

find . -name "*.sh" -type f | while read file; do
    echo "处理:$file"

注意:这里是在子Shell中执行

done


**如果要处理带空格的文件名,必须用这个版本:**

```bash
find . -name "*.sh" -type f -print0 | while IFS= read -r -d '' file; do
    echo "安全处理:$file"
done

看到-print0和read -d ''了吗?这是处理任意文件名的黄金组合,连换行符都能正确处理!

1到100求和:Shell脚本的数学之美

你以为Shell不能做数学?那就太小看它了!

方法一:用for循环

!/bin/bash

sum=0 for ((i=1; i<=100; i++)); do sum=$((sum + i)) done echo “1到100的和是:$sum”


**方法二:用seq和awk(更简洁)**

```bash
seq 1 100 | awk '{sum+=$1} END{print "和是:" sum}'

方法三:直接用数学公式

echo $((100*101/2))

但这里有个坑要注意:Shell默认只处理整数。如果你需要小数运算,得用bc:

echo "scale=2; 1/3" | bc

输出:.33

一箭双雕:如何同时输出到屏幕和文件?

这个需求太常见了!你运行一个脚本,既想在屏幕上看到实时输出,又想保存日志供后来查看。

最简单的方法:tee命令

./your_script.sh | tee logfile.txt

但这样只能保存标准输出,错误信息呢?看这个:

./your_script.sh 2>&1 | tee logfile.txt

2>&1把标准错误重定向到标准输出,这样所有输出都被tee捕获了。

如果你想追加到日志文件,而不是覆盖:

./your_script.sh 2>&1 | tee -a logfile.txt

更高级的用法:分离输出

有时候你想把正常输出和错误输出分开保存:

./your_script.sh > >(tee stdout.log) 2> >(tee stderr.log >&2)

这个语法有点复杂,但功能强劲。>(…)是进程替换,让tee能同时处理数据。

$0、$1、$@、$#:脚本参数的秘密语言

这几个符号天天见,但你真的清楚它们的区别吗?

$0:当前脚本的名字。但有个小秘密:如果脚本是通过符号链接执行的,$0是链接的名字,不是实际脚本名!

$1、$2…:位置参数。第一个参数、第二个参数…

$@和$*:所有参数。但它们有重大区别!看这个例子:

!/bin/bash

echo “用@:” for arg in “$@”; do echo “参数:[$arg]” done

echo “用*:” for arg in “$*”; do echo “参数:[$arg]” done


运行`./test.sh a b "c d"`,你会发现:

`"$@"`保留了参数边界,三个参数:a、b、"c d"

`"$*"`把所有参数合并成一个字符串:"a b c d"

`$#`:参数个数。判断是否有参数时特别有用:

```bash
if [ $

-eq 0 ]; then

echo “用法:$0 <文件名>…” exit 1 fi

如何判断一个文件是不是可执行的Shell脚本?

这个问题看似简单,实则暗藏玄机!

初级做法:检查扩展名

if [[ $file == *.sh ]]; then
    echo "看起来是个Shell脚本"
fi

但这样不靠谱!文件可以没有.sh扩展名,或者有.sh扩展名但不是脚本。

中级做法:检查文件头

if head -1 "$file" | grep -q "^#!/bin/bash|^#!/bin/sh"; then
    echo "这是个Shell脚本!"
fi

高级做法:综合判断

is_shell_script() {
    local file="$1"

必须是普通文件

[ -f “$file” ] || return 1

必须有可执行权限

[ -x “$file” ] || return 1

检查文件头

case $(head -1 “$file”) in “#!/bin/bash”|”#!/bin/sh”|”#!/usr/bin/env bash”|”#!/usr/bin/env sh”) return 0 ;; *)

还可以检查文件内容

if grep -q “^[[:space:]]*function|^[[:space:]]*if|^[[:space:]]*for” “$file” 2>/dev/null; then return 0 fi return 1 ;; esac }


**最准确的方法:用file命令**

```bash
if file "$file" | grep -q "Bourne-Again shell script|POSIX shell script"; then
    echo "确定是Shell脚本!"
fi

awk和cut:文本处理的双子星,你选哪个?

awk '{print $1}'和cut -d' ' -f1看起来功能类似,但差别大了去了!

cut的局限性:

分隔符只能是一个字符

对连续分隔符处理有问题:echo “a b” | cut -d' ' -f2 输出是空,不是b!

不能重新排列字段

awk的强劲之处:

分隔符可以是正则表达式:awk -F'[ ,]+' '{print $1}'

自动处理连续分隔符

能做计算:awk '{print $1, $2, $1+$2}'

能条件过滤:awk '$1 > 100 {print $0}'

看这个实际例子:

处理/etc/passwd

cut -d: -f1,7 /etc/passwd

只能输出两个字段

awk -F: '{print $1, $7}' /etc/passwd

同样功能

但awk还能这样:

awk -F: '{printf “用户%-10s 使用shell:%s
“, $1, $7}' /etc/passwd


**简单规则:简单字段提取用cut,复杂处理用awk**。不过目前许多人直接全用awk,由于功能更强劲。

sed替换技巧:不仅仅是s/old/new/g

s/old/new/g是最基本的sed用法,但sed的能力远不止于此!

基础替换:

sed 's/old/new/g' file.txt

只替换每行的第N次出现:

sed 's/old/new/2' file.txt

只替换第二次出现


**从第M行开始替换:**
```bash
sed '10,$ s/old/new/g' file.txt

从第10行到最后一行


**替换时忽略大小写(GNU sed):**
```bash
sed 's/old/new/gi' file.txt

更安全的替换:使用分隔符 当替换内容包含斜杠时:

错误做法:

sed 's/path/to/file//new/path//g'

语法错误!

正确做法:换分隔符

sed 's|path/to/file|/new/path|g' sed 's#path/to/file#/new/path#g'


**原地替换文件(危险但有用):**
```bash
sed -i.bak 's/old/new/g' file.txt

备份原文件为file.txt.bak

#!/bin/bash和#!/bin/sh:一字之差,天壤之别!

这个问题太重大了!选错了解释器,你的脚本可能到处报错。

#!/bin/sh:指向系统默认的Shell,可能是bash,也可能是dash、ksh等。在Debian/Ubuntu上,/bin/sh一般是dash,一个更轻量但功能较少的Shell。

#!/bin/bash:明确使用Bash,功能最强劲。

关键区别:

[[ ]]、(( ))在sh里可能不支持

数组在sh里可能不支持

进程替换<(cmd)在sh里可能不支持

安全做法:

如果你用了Bash特有功能,必定用#!/bin/bash

如果想写可移植脚本,用#!/bin/sh,但不要用任何扩展功能

更现代的写法:#!/usr/bin/env bash,这样会使用环境中的bash,更灵活

source的秘密:为什么它能改变当前Shell?

这个问题触及了Shell执行的核心机制!

普通执行:./script.sh 或 bash script.sh

启动新的子Shell

脚本在子Shell中运行

脚本结束后,子Shell退出

所有变量、函数、别名都消失

source执行:source script.sh 或 . script.sh

在当前Shell中直接执行脚本

相当于把脚本内容粘贴到当前位置执行

所有改变都保留在当前Shell中

看这个例子:

config.sh

export DATABASE_URL=”mysql://user:pass@localhost/db” alias ll=”ls -la”

普通执行

./config.sh echo $DATABASE_URL

输出空!变量没了

ll

命令找不到!别名没了

source执行

source config.sh echo $DATABASE_URL

输出正确!

ll

正常工作!


**这就是为什么环境配置脚本都要用source执行!** `.bashrc``.profile`这些文件,如果你改了之后想让配置立即生效,必须执行`source ~/.bashrc`**但要注意危险:** source会改变当前环境,如果脚本里有`exit`,它会直接退出当前Shell!所以source别人的脚本要特别小心。

看完这些,你是不是对Shell脚本有了全新的认识?那些曾经困扰你的问题,目前都有答案了吧!记住,Shell脚本不是玩具,而是强劲的自动化工具。用好了,它能帮你节省无数时间;用不好,它也能制造无数bug。

最好的学习方法就是动手实践。打开终端,把这些例子都敲一遍,感受一下它们的细微差别。信任我,当你真正理解这些概念后,写Shell脚本会变成一种享受!

别再盲目复制粘贴了,理解原理,写出优雅可靠的脚本,这才是程序员的自我修养。从今天开始,让你的Shell脚本水平提升一个档次!

© 版权声明

相关文章

暂无评论

none
暂无评论...