- LoopX
- اسکریپتنویسی Bash
- دستورات Bash: برگهی تقلب اسکریپتنویسی
دستورات Bash: برگهی تقلب اسکریپتنویسی
همهی دستورهای دورهی اسکریپتنویسی Bash در یک صفحه: ۱۶۳ دستور از ۱۴ درس، به ترتیب درسها. هر دستور در درس خودش با خروجی واقعی اجرا و توضیح داده شده است؛ روی اسم درس بزن تا توضیح کامل و مثالها را ببینی.
مبانی
اولین اسکریپت
| دستور | کاری که میکند |
|---|---|
#!/usr/bin/env bash | خط اول: اجرا با bash (قابلحمل) |
chmod +x script.sh | دادن مجوز اجرا |
./script.sh | اجرای مستقیم (نیاز به x و shebang) |
bash script.sh | اجرا بدون نیاز به x؛ shebang نادیده |
source script.sh / . script.sh | اجرا در همین shell (cd و متغیرها میمانند) |
# توضیح | کامنت؛ تا آخر خط |
bash -n script.sh | بررسی نحو بدون اجرا |
exit 3 | پایان اسکریپت با کد ۳ |
echo $? | کد خروج آخرین دستور |
file script.sh | تشخیص نوع فایل (از روی shebang) |
sed -i 's/\r$//' file | تبدیل CRLF ویندوز به LF |
متغیرها و نقلقول
| دستور | کاری که میکند |
|---|---|
name="value" | تعریف متغیر (بدون فاصله دور =) |
echo "$name" | خواندن متغیر، همیشه با کوتیشن دوتایی |
echo '$name' | متن دقیق، بدون جایگزینی |
"${name}_backup" | آکولاد برای مشخصکردن مرز اسم |
today=$(date +%F) | خروجی دستور در متغیر |
$((a + b)) $((a * b)) | محاسبهی عدد صحیح |
((count++)) ((count += 5)) | تغییر شمارنده |
$((10#$month + 1)) | محاسبه با عدد دارای صفر اول |
date +%F_%H-%M-%S | تاریخ و ساعت برای اسم فایل |
readonly PI=3.14 unset name | ثابت واقعی / پاککردن متغیر |
printf '[%s]\n' $var | دیدن اینکه شل متغیر را چند تکه کرد |
${dir:?پیام} | اگر خالی بود، پیام بده و متوقف شو |
ورودی و آرگومانها
| دستور | کاری که میکند |
|---|---|
read -r -p "Name: " name | پرسیدن از کاربر |
read -s -p "Password: " pass | خواندن رمز بدون نمایش |
read -t 5 var / read -n 1 key | با زمانسنج / فقط یک کاراکتر |
read a b rest <<< "x y z w" | شکستن یک خط به چند متغیر |
echo "$1" ${10} | آرگومان اول / آرگومان دهم |
echo "$#" | تعداد آرگومانها |
"$@" | همهی آرگومانها، هر کدام جدا |
shift / shift 2 | دور انداختن اولین آرگومان (یا دو تای اول) |
if [[ $# -ne 1 ]]; then ... exit 1; fi | بررسی تعداد آرگومان (مثال ۶) |
echo "Usage: $0 <file>" >&2 | راهنما روی stderr |
name="${1:-World}" | مقدار پیشفرض برای آرگومان |
printf '[%s]\n' "$@" | دیدن اینکه هر آرگومان چطور رسید |
شرطها
| دستور | کاری که میکند |
|---|---|
if [[ -f file ]]; then ... fi | اگر فایل معمولی است |
if ...; then ... elif ...; then ... else ... fi | چند شاخه |
[[ $a -gt $b ]] | عدد: -eq -ne -lt -le -gt -ge |
(( a > b )) | مقایسهی عدد با ریاضی |
[[ $s == "Ali" ]] [[ -z $s ]] | رشته: برابر / خالی |
[[ $f == *.txt ]] [[ $d =~ ^[0-9]+$ ]] | الگو / regex |
[[ -e p ]] [[ -d p ]] [[ -s p ]] | وجود / پوشه / غیرخالی |
[[ -r p && -w p ]] | ترکیب با && (و || و !) |
mkdir -p d && cd d / cmd || exit 1 | اگر موفق شد / اگر شکست خورد |
echo $? | کد خروج آخرین دستور (۰ = موفق) |
if ! grep -q x file; then ... | نفی یک دستور |
bash -n script.sh | بررسی نحو پیش از اجرا |
case
| دستور | کاری که میکند |
|---|---|
case "$1" in start) ... ;; stop) ... ;; *) ... ;; esac | ساختار کامل |
de | at) | چند الگو (یا) |
*.txt) [0-9]*) ?) | الگوهای wildcard |
*) | پیشفرض؛ آخر بنویس |
shopt -s nocasematch | نادیدهگرفتن حروف بزرگ و کوچک |
shopt -s extglob +([0-9]) | الگوی «یک یا چند رقم» |
;& ;;& | ادامهی بیقید / آزمون الگوهای بعدی (bash 4+) |
command="$1"; shift; case "$command" in ... | اسکریپت با زیردستور |
kill -0 PID | بررسی زندهبودن پروسه (بدون سیگنال) |
PS3="Pick: "; select x in a b c; do ...; done | منوی آماده |
حلقهها
| دستور | کاری که میکند |
|---|---|
for f in *.log; do ...; done | برای هر فایل |
for i in {1..5} | بازهی ثابت (نزولی {5..1}، قدم {0..10..2}) |
for ((i=1; i<=n; i++)); do ...; done | حلقهی C-style با متغیر |
while (( i < 5 )); do ...; done | تا وقتی شرط برقرار است |
until [[ -e file ]]; do sleep 1; done | تا وقتی شرط برقرار شود |
break / continue / break 2 | خروج / دور بعد / خروج از دو حلقه |
while IFS= read -r line; do ...; done < file | فایل خطبهخط |
while read -r a b c; do ...; done < file | شکستن هر خط به فیلد |
... done < <(grep x file) | حلقه روی خروجی دستور بدون subshell |
shopt -s nullglob | الگوی بیتطابق ← حلقه اجرا نشود |
mv -n -- "$f" "$new" | تغییر نام بدون رونویسی |
timeout 5 command | کشتن دستور بعد از ۵ ثانیه |
ساختارمند نوشتن
تابعها
| دستور | کاری که میکند |
|---|---|
greet() { echo "Hello, $1"; } | تعریف تابع (قبل از استفاده) |
greet Ali | صدازدن؛ آرگومانها در $1 و $# |
x=$(add 2 3) | گرفتن خروجی (echo) تابع |
is_dir() { [[ -d $1 ]]; } if is_dir x; then | تابع شرط: کد خروج |
return 3 / exit 1 | برگشت از تابع / بستن کل اسکریپت |
local var local out; out=$(cmd) | متغیر محلی؛ بدون پنهانکردن کد خروج |
log() { echo "$(date +%T) $*" | tee -a "$LOG"; } | چاپ و ثبت در فایل |
die() { echo "Error: $*" >&2; exit 1; } | خطا و خروج |
source "$script_dir/lib.sh" | آوردن کتابخانهی توابع |
declare -f name type -a name | دیدن تعریف / همهی معنیهای یک اسم |
unset -f name command name | حذف تابع / رد کردن تابع |
export -f name | رساندن تابع به bash فرزند |
آرایهها
| دستور | کاری که میکند |
|---|---|
arr=(a b "c d") arr+=(e) | ساخت / افزودن |
"${arr[@]}" ${arr[0]} ${arr[-1]} | همه (جدا جدا) / یک عضو / آخرین |
${#arr[@]} "${!arr[@]}" | تعداد / اندیسها |
for x in "${arr[@]}"; do ...; done | پیمایش مقدارها |
for i in "${!arr[@]}"; do ...; done | پیمایش با اندیس |
unset 'arr[1]' arr=("${arr[@]}") | حذف (سوراخ) / فشردهسازی مجدد |
files=(*.txt) | آرایه از فایلها (امن برای فاصله) |
mapfile -t lines < file | هر خط فایل یک عضو |
IFS=, read -ra parts <<< "a,b,c" | شکستن رشته به آرایه |
declare -A map; map[k]=v | آرایهی انجمنی |
"${!map[@]}" [[ -v map[k] ]] ((map[$k]++)) | کلیدها / وجود کلید / شمارش |
declare -p arr | دیدن ساختار دقیق آرایه |
کار با رشتهها
| دستور | کاری که میکند |
|---|---|
${#s} ${s:2:3} ${s: -3} | طول / برش / سه کاراکتر آخر |
${p##*/} ${p%/*} | اسم فایل / پوشه (basename و dirname) |
${f##*.} ${f%.*} ${f%%.*} | پسوند / بیآخرینپسوند / بیهمهیپسوندها |
${f%.txt}.md | تغییر پسوند |
${s#pat} ${s##pat} ${s%pat} ${s%%pat} | حذف پیشوند/پسوند (کوتاه و بلند) |
${s/old/new} ${s//old/new} | جایگزینی اولی / همه |
${s//[^a-z0-9]/} | حذف هر چیز جز حرف و عدد |
${s^^} ${s,,} ${s^} | بزرگ / کوچک / حرف اول بزرگ (Bash 4+) |
${v:-d} ${v:=d} ${v:+alt} | پیشفرض / پیشفرض و ذخیره / فقط اگر مقدار دارد |
${v:?پیام} | اگر خالی بود، پیام و توقف |
"${files[@]%.txt}" | حذف پسوند از همهی عضوهای آرایه |
${!name} ${s@Q} | گسترش غیرمستقیم / رشتهی امن برای استفادهی مجدد |
here-doc و پردازش متن در اسکریپت
| دستور | کاری که میکند |
|---|---|
cat <<EOF > file ... EOF | نوشتن متن چندخطی با گسترش متغیر |
cat <<'EOF' | متن خام (بدون گسترش) |
cat <<-EOF | تورفتگی با tab مجاز |
cat >> file <<EOF | افزودن به انتهای فایل |
sudo tee file > /dev/null <<EOF | نوشتن در فایل نیازمند root |
var=$(cat <<EOF ... EOF) | ریختن متن چندخطی در متغیر |
grep -c pat f grep -q pat f grep -F "$x" f | شمارش / فقط کد خروج / متن دقیق |
grep -oE "[0-9.]+" f | sort | uniq -c | sort -rn | شمردن و رتبهبندی |
sed "s|__KEY__|$value|g" tpl | پرکردن قالب (جداکنندهی |) |
sed -i.bak "s/old/new/" f | ویرایش درجا (GNU و macOS) |
awk '$9 >= 400 {print $1}' f | شرط روی ستون |
awk -v min="$x" '$10 > min' f awk '{c[$9]++} END {...}' | متغیر شل با -v / شمارش با آرایه |
اسکریپت حرفهای
مدیریت خطا
| دستور | کاری که میکند |
|---|---|
set -euo pipefail | توقف در خطا، متغیر تعریفنشده خطا، شکست وسط pipe |
set -Eeuo pipefail | همان، بهعلاوهی اجرای trap ERR داخل تابعها |
shopt -s inherit_errexit | اثر set -e داخل $(...) |
trap cleanup EXIT | پاکسازی در هر نوع خروج |
trap 'echo "line $LINENO: $BASH_COMMAND"' ERR | گزارش خط و دستور شکستخورده |
tmp="$(mktemp -d)" | پوشهی موقت امن و یکتا |
exit 2 die() { echo "$*" >&2; exit 1; } | پایان با کد خروج معنادار |
cmd || true if ! cmd; then | شکست قابلانتظار، بدون توقف |
echo "${PIPESTATUS[@]}" | کد خروج همهی عضوهای آخرین pipe |
${var:-} | متغیر اختیاری با set -u |
trap -p trap - EXIT | دیدن و برداشتن trapها |
echo $- set -o | گزینههای فعلی شل |
گزینههای خط فرمان با getopts
| دستور | کاری که میکند |
|---|---|
while getopts ":hvo:" opt; do case $opt in ... esac; done | حلقهی استاندارد خواندن گزینهها |
o) output=$OPTARG ;; | مقدار گزینهی دارای : |
\?) echo "unknown -$OPTARG" >&2; exit 2 ;; | گزینهی ناشناخته (حالت بیصدا) |
:) echo "-$OPTARG needs a value" >&2; exit 2 ;; | مقدار جاافتاده (حالت بیصدا) |
shift $((OPTIND - 1)) | کنار گذاشتن گزینهها؛ عملوندها در "$@" |
./script.sh -v -- -file | پایان گزینهها |
usage() { cat <<EOF ... EOF; } | پیام راهنما |
[[ $n =~ ^[0-9]+$ ]] || die_usage "..." | اعتبارسنجی عدد |
while (( $# > 0 )); do case $1 in --help) ...;; esac; shift; done | گزینههای بلند با حلقهی دستی |
--output=*) output=${1#*=} ;; | گزینهی بلند با = |
local OPTIND=1 | getopts داخل تابع |
دیباگ و کیفیت کد
| دستور | کاری که میکند |
|---|---|
bash -n script.sh | بررسی نحو بدون اجرا |
bash -x script.sh | اجرا با trace کامل |
set -x ... set +x | trace فقط یک بخش |
PS4='+ ${BASH_SOURCE##*/}:${LINENO}: ' | فایل و شمارهی خط در trace |
exec 7>trace.log; BASH_XTRACEFD=7 | trace در فایل جدا |
declare -p var | نوع و مقدار دقیق متغیر |
echo "DEBUG: $x" >&2 | پیام دیباگ روی stderr |
shellcheck script.sh | تحلیل ایستا |
shellcheck -f diff s.sh > fix.diff; patch -p1 < fix.diff | اعمال اصلاحهای خودکار |
# shellcheck disable=SC2086 | ساکت کردن آگاهانهی یک هشدار |
shfmt -i 4 -d s.sh shfmt -i 4 -w s.sh | دیدن و اعمال قالببندی |
پروژه: بکاپ خودکار و بررسی سلامت سرور
| دستور | کاری که میکند |
|---|---|
find "$dest" -maxdepth 1 -name "$base-*.tar.gz" -mtime +7 -print -delete | چرخش امن بکاپهای قدیمی |
tar -czf "$tmp/$a" -C "$(dirname "$src")" "$(basename "$src")" | آرشیو با مسیر نسبی |
tar -tzf archive.tar.gz > /dev/null | بررسی سالمبودن آرشیو |
tmp=$(mktemp -d -p "$dest" .tmp.XXXXXX) | پوشهی موقت کنار مقصد |
exec 9> /run/lock/x.lock; flock -n 9 || exit 75 | یک نسخه در هر لحظه |
logger -t lx-backup -p user.err -- "msg" | نوشتن در syslog |
install -m 755 tool /usr/local/bin/ | نصب ابزار |
crontab -e crontab -l crontab -l | sed ... | crontab - | ویرایش، دیدن و جایگزینی crontab |
30 2 * * * /usr/local/bin/lx-backup /srv/shop | هر شب ۲:۳۰ |
*/5 * * * * /usr/local/bin/lx-health -q | هر ۵ دقیقه، فقط موقع مشکل خروجی |
grep CRON /var/log/syslog | آیا cron کار را اجرا کرد؟ |
df -P / systemctl is-active nginx | دیسک و وضعیت سرویس |
دستوری با این عبارت پیدا نشد.