# 開發工具指南 Part2 時間:2023/11/09 講者:Ethan [簡報連結](https://docs.google.com/presentation/d/1xYXvNkCLcJP9bsu8LSe3VPizCnoQC5Oe-luWiy2eUh8/edit#slide=id.p1) # introduction **什麼是shell** - 用於存取作業系統服務的使用者介面 - 常見的 shell 包括 Bash、Zsh 和 Sh - 用於執行命令、管理文件和運行腳本 **什麼是Bash scripting** - script : 一個文字文件,包含一系列命令 - Bash script : 是以 Bash shell 語法編寫腳本實現日常任務、複雜操作等的自動化 **Bash vs Python**  # Basics of the Shell **GUI vs Command line** - GUI: 直觀,適合簡單的任務 - Command Line: 強大、靈活、高效,可完成複雜任務 **Understanding the File System Tree** Unix-like OS 有從 root 開始的樹狀目錄結構 - root: 包含所有檔案和子目錄 Unix-like systems 維護一個檔案系統樹 - Pathnames(路徑名稱): 絕對:從 root 開始(例如 /usr/bin)。 相對:從目前目錄開始,而不是根目錄。 - Special Notations: .:表示目前工作目錄。 ..:表示目前工作目錄的父目錄。 **Options and Arguments** 指令的結構 - command [-options] [arguments] - Options: 短:破折號後的單一字元 e.g. -v 長:兩個破折號後的單字 e.g. --version 組合短選項:e.g. ls -lt - Arguments: 命令操作的目標 e.g. filename, path, … **基礎的shell指令** - ls:列出目錄內容 - cd:更改目前目錄 - pwd:列印工作目錄 - echo:輸出文字到終端 - cat:輸出文件到終端 - clear:清除終端的輸出 **core commands** - cp:複製檔案/目錄 - mv:移動/重新命名檔案/目錄 - mkdir:建立目錄 - rm:刪除檔案/目錄 - touch: 建立文件 **Wildcard Characters(萬用字元)** - **\*** : 任意長度的字元 - **?** : 任意的單一字元 **使用'rm'時請小心** - No Undo: Unix-like OS 缺乏「復原」功能。 一旦使用 rm 刪除,很難找回來 - Wildcard Risks: 可能會導致意外刪除 Example: - Intended: rm *.html - Mistake: rm * .html # Redirection **Standard I/O Channels** - Input (stdin): 通常來自鍵盤,也可以從檔案導入 - Output (stdout): 輸出,顯示在螢幕上或輸出到檔案 - Error (stderr): 錯誤訊息,顯示在螢幕上或輸出到檔案 **Basic Redirection** - <: Input ```sort < unsorted.txt``` - \>: Redirects and truncates ```ls -l > output.txt``` - \>>: Redirects and appends ```ls -l >> output.txt``` **Error Redirection** - 2>: 導出stderr ```ls -l /bin/usr 2> error.txt``` - 組合輸出和錯誤 \> file 2>&1 or &> file: stdout 和 stderr 輸出到相同檔案。 ```ls -l /bin/usr &> ls-output.txt``` - 靜音輸出 /dev/null: 處理不需要的輸出 ```ls -l /bin/usr 2> /dev/null``` **Exit Statuses** - 0表示命令成功執行,沒有任何錯誤 - 其他(通常在1和之間255)都表示錯誤 **The Power of grep** 在指定文件中搜尋與 pattern(關鍵字) 相符的行,並列印它們。 Syntax(語法): ```grep [pattern] [filename]``` **Viewing File Extremities** - head:顯示檔案的開頭 - tail:顯示文件結尾 ``` Usage: head -n 5 filename ``` **Pipelines** Pipelines允許一個命令的輸出用作另一個命令的輸入 ``` Syntax: command1 | command2 ``` ``` example: ls -l /usr/bin | grep "bash" ``` # Bash Scripting **basic** - Shebang - 由`#!`構成 - 識別腳本的解釋器 - #!/bin/bash - 副檔名: .sh - 注解:# **Execute your script** 先讓你的script可執行 ``` chmod +x script_name.sh ``` 接著直接執行它 ``` ./script_name.sh ``` **Variables** - 語法: ``` #variable=value a=5 ``` (錯誤範例) ``` a = 5 a= 5 a =5 ``` - 要呼叫變數時使用'$' ``` a="a string" b="a string and $a" c="$(ls -1 foo.txt)" FOO=1 ``` (錯誤範例) ``` $FOO + 1 #Error ``` - 輸入 ``` # read -p ["一些你想輸入的文字"] [目標] read -p "send: " FOO ``` **Argument** - $0 - 腳本名稱 - $1-$9 - 腳本的參數。 $1 是第一個參數,依此類推。 - $@ - 所有參數 - $# - 參數數量 - $? - 上一個指令的返回碼 **Conditionals** ``` false || echo "Oops, fail" # Oops, fail true || echo "Will not be printed" # true && echo "Things went well" # Things went well false && echo "Will not be printed" # true ; echo "This will always run" # This will always run false ; echo "This will always run" # This will always run ``` 一些常用符號 - -eq:== - -ne:!= - -gt:> - -ge:>= - -lt:< - -le:<= **File Expressions** - -d file:如果檔案存在且是目錄,則為 true。 - -e file:如果檔案存在則為true。 - file1 -nt file2:如果 file1 比 file2 新,則為 True。 - file1 -ot file2:如果 file1 早於 file2,則為 True。 **Conditionals** ``` if [ condition1 ]; then COMMANDS1 elif [ condition2 ]; then COMMANDS2 else COMMANDS3 fi ``` **Case** ``` case <expression> in pattern1) commands1;; pattern2) commands2;; *) default_commands;; esac ``` ``` case $1 in start) echo "Starting the service...";; stop) echo "Stopping the service...";; restart) echo "Restarting the service...";; *) echo "Usage: $0 {start|stop|restart}";; esac ``` **for loops** ``` NAMES="a b c d" for NAME in $NAMES do echo "Hello $NAME" done ``` (c language form) ``` for ((expression1; expression2; expression3 )); do commands done ``` ``` #!/bin/bash # simple_counter: demo of C style for command for ((i=0; i<5; i=i+1)); do echo $i done ``` **Sequence** - seq LAST - seq FIRST LAST - seq FIRST INCREMENT LAST ``` for i in $(seq 1 5); do echo "Number $i" done ``` **while loops** ``` while TEST-COMMANDS; do CONSEQUENT-COMMANDS done ``` ``` #!/bin/bash # while-count: display a series of numbers count=1 while [[ "$count" -le 5 ]]; do echo "$count" count=$((count + 1)) done echo "Finished." ``` **function** ``` function function_name () { # Code to execute commands return [n] # Optional } ``` ``` function greet { echo "Hello!" } ``` ``` #!/bin/bash # Define the function greet () { echo "Hello, $1!" } # Call the function greet "Alice" greet "Bob" ``` # NOTE - 不要執行自己不認識的命令 - 不會寫就找 ChatGPT 寫 - 組合不同的程式一起使用 e.g. python + bash # 練習答案 ## ex1 `mkdir ex1` `mkdir ex1/dir1 ex1/dir2` `cat /etc/issue` `cp /etc/issue ex1/dir1` `cp /etc/issue ex1/dir2` `mv ex1/dir2/issue ex1/dir2/sys` ## ex2 `grep -rn "handle__subscribe" .` ## ex3 ```bash= #!/bin/bash if [ $# -eq 0 ]; then echo "Usage: $0 extension" exit 1 fi # Create the directory if it doesn't exist [ -d "$1" ] || mkdir "$1" # Move the files mv *."$1" "$1" ``` ## ex4 ```bash= #!/bin/bash echo "Menu" echo "1) date\n 2) ls\n 3) who\n 4) pwd\n 5) exit" while : do read -p "Enter your choice: " choice case $choice in 1) date;; 2) ls;; 3) who;; 4) pwd;; 5) exit;; *) echo "Invalid choice" echo "1) date\n 2) ls\n 3) who\n 4) pwd\n 5) exit";; esac done ``` ## ex5 ```bash!= #!/bin/bash if [ $# -eq 0 ]; then echo "fib needs arg" exit 1 fi fib() { N="$1" if [ "$N" -eq 0 ]; then echo 0 elif [ "$N" -eq 1 ]; then echo 1 else echo $(( $( fib $((N-1)) ) + $( fib $((N-2)) ) )) fi } for i in $( seq 0 "$1" ); do fib "$i" done ``` ## ex6 ```bash= #!/bin/bash if [ "$#" -ne 2 ]; then echo "Usage: $0 <file_without_extension> <number_of_testcases>" exit 1 fi hw_name="$1" # compile the program g++ "$hw_name".cpp -o "$hw_name" # get the number of testcases for i in $( seq 1 $2 ); do test_in="./testcases/input/$1-$i.in" test_out="./testcases/output/$1-$i.out" tmp_output="./testcases/tmp_output/"$1"-"$i".out" if [ -e "$test_in" ]; then # run the program, input from test_in, output to tmp_output ./"$1" < $test_in > $tmp_output test_case=$1-$i # use diff to compare the output and redirect the unwanted output to /dev/null if diff -q "$tmp_output" "$test_out" > /dev/null; then echo "Test $test_case passed" else echo "Test $test_case failed" fi else echo "Input file $test_in does not exist" fi done ```
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up