第167集:字符串处理
教学目标
- 掌握Shell脚本中字符串的基本操作方法
- 学习字符串的比较和测试
- 理解字符串的查找和替换操作
- 掌握字符串的格式化和拼接
- 学习字符串的转换和处理技巧
- 能够在脚本中灵活处理各种字符串操作
主要知识点
- 字符串的基本操作
- 字符串的长度计算
- 字符串的拼接
- 字符串的截取
- 字符串的比较
- 字符串的查找和替换
- 字符串的格式化
- 字符串的转换
- 字符串的分割和连接
实用案例分析
案例1:字符串基本操作
目标:学习Shell脚本中字符串的基本操作。
操作步骤:
- 创建字符串基本操作演示脚本
# 创建脚本文件
touch string-basics.sh
# 编辑脚本文件
vim string-basics.sh
# 添加以下内容
#!/bin/bash
# 演示字符串基本操作
# 1. 定义字符串
str1="Hello"
str2='World'
str3="Linux Operating System"
# 2. 计算字符串长度
echo "=== Calculating string length ==="
echo "Length of str1: ${#str1}"
echo "Length of str2: ${#str2}"
echo "Length of str3: ${#str3}"
# 3. 字符串拼接
echo "\n=== String concatenation ==="
# 方法1:直接连接
combined1="$str1 $str2"
echo "Combined 1: $combined1"
# 方法2:使用+号(注意:Bash中+不是字符串连接符)
combined2=$str1" "$str2
echo "Combined 2: $combined2"
# 方法3:使用变量展开
combined3=${str1} ${str2}
echo "Combined 3: $combined3"
# 4. 字符串截取
echo "\n=== String slicing ==="
# 从索引0开始,取5个字符
slice1=${str3:0:5}
echo "First 5 characters: $slice1"
# 从索引6开始,取9个字符
slice2=${str3:6:9}
echo "Characters from index 6: $slice2"
# 从索引16开始,取到末尾
slice3=${str3:16}
echo "Characters from index 16 to end: $slice3"
# 从末尾开始取5个字符
slice4=${str3: -5}
echo "Last 5 characters: $slice4"
# 5. 字符串变量展开
echo "\n=== Variable expansion ==="
# 变量替换
name="Alice"
echo "Hello, ${name}!"
# 变量默认值
unset var
echo "Default value: ${var:-'No value'}"
# 变量赋值默认值
var=${var:-'New value'}
echo "After assignment: $var"
# 变量存在性检查
echo "Variable exists: ${var:+'Yes'}"- 运行脚本并查看结果
# 设置执行权限
chmod +x string-basics.sh
# 运行脚本
./string-basics.sh案例2:字符串比较
目标:学习在Shell脚本中比较字符串。
操作步骤:
- 创建字符串比较演示脚本
# 创建脚本文件
touch string-comparison.sh
# 编辑脚本文件
vim string-comparison.sh
# 添加以下内容
#!/bin/bash
# 演示字符串比较
# 定义测试字符串
str1="apple"
str2="banana"
str3="apple"
# 1. 使用test命令比较
echo "=== Using test command ==="
if test "$str1" = "$str3"; then
echo "str1 equals str3"
fi
if test "$str1" != "$str2"; then
echo "str1 not equals str2"
fi
# 2. 使用[ ]比较
echo "\n=== Using [ ] ==="
if [ "$str1" = "$str3" ]; then
echo "str1 equals str3"
fi
if [ "$str1" != "$str2" ]; then
echo "str1 not equals str2"
fi
# 3. 使用[[ ]]比较(支持通配符)
echo "\n=== Using [[ ]] ==="
if [[ "$str1" == "a*" ]]; then
echo "str1 starts with 'a'"
fi
if [[ "$str2" == *"na" ]]; then
echo "str2 ends with 'na'"
fi
if [[ "$str3" == *"ppl"* ]]; then
echo "str3 contains 'ppl'"
fi
# 4. 字符串大小比较(字典序)
echo "\n=== Lexicographical comparison ==="
if [[ "$str1" < "$str2" ]]; then
echo "str1 comes before str2"
fi
if [[ "$str2" > "$str3" ]]; then
echo "str2 comes after str3"
fi
# 5. 检查字符串是否为空
echo "\n=== Checking for empty strings ==="
empty_str=""
unset unset_str
if [ -z "$empty_str" ]; then
echo "empty_str is empty"
fi
if [ -n "$str1" ]; then
echo "str1 is not empty"
fi
if [ -z "$unset_str" ]; then
echo "unset_str is empty"
fi- 运行脚本并查看结果
# 设置执行权限
chmod +x string-comparison.sh
# 运行脚本
./string-comparison.sh案例3:字符串查找和替换
目标:学习在Shell脚本中查找和替换字符串。
操作步骤:
- 创建字符串查找和替换演示脚本
# 创建脚本文件
touch string-search-replace.sh
# 编辑脚本文件
vim string-search-replace.sh
# 添加以下内容
#!/bin/bash
# 演示字符串查找和替换
# 定义测试字符串
str="Hello Linux World! Linux is great."
# 1. 查找子字符串
echo "=== Searching for substrings ==="
# 使用grep查找
if echo "$str" | grep -q "Linux"; then
echo "'Linux' found in string"
fi
# 使用[[ ]]查找
if [[ "$str" == *"World"* ]]; then
echo "'World' found in string"
fi
# 2. 替换子字符串
echo "\n=== Replacing substrings ==="
# 替换第一个匹配项
replaced1=${str/Linux/Unix}
echo "Replace first 'Linux': $replaced1"
# 替换所有匹配项
replaced2=${str//Linux/Unix}
echo "Replace all 'Linux': $replaced2"
# 替换开头的匹配项
replaced3=${str/#Hello/Hi}
echo "Replace 'Hello' at start: $replaced3"
# 替换结尾的匹配项
replaced4=${str/%great./awesome!}
echo "Replace 'great.' at end: $replaced4"
# 3. 使用sed命令替换
echo "\n=== Using sed for replacement ==="
# 替换所有匹配项
sed_replaced=$(echo "$str" | sed 's/Linux/Unix/g')
echo "sed replace all: $sed_replaced"
# 替换第2个匹配项
sed_replaced2=$(echo "$str" | sed 's/Linux/Unix/2')
echo "sed replace second occurrence: $sed_replaced2"
# 4. 查找子字符串位置
echo "\n=== Finding substring position ==="
# 使用awk查找
pos=$(echo "$str" | awk -F'Linux' '{print length($1)}')
echo "Position of first 'Linux': $pos"
# 5. 提取子字符串
echo "\n=== Extracting substrings ==="
# 提取第一个单词
first_word=$(echo "$str" | cut -d' ' -f1)
echo "First word: $first_word"
# 提取从第7个字符开始的字符串
extracted=${str:6}
echo "Extracted from index 6: $extracted"- 运行脚本并查看结果
# 设置执行权限
chmod +x string-search-replace.sh
# 运行脚本
./string-search-replace.sh案例4:字符串格式化和转换
目标:学习在Shell脚本中格式化和转换字符串。
操作步骤:
- 创建字符串格式化和转换演示脚本
# 创建脚本文件
touch string-formatting.sh
# 编辑脚本文件
vim string-formatting.sh
# 添加以下内容
#!/bin/bash
# 演示字符串格式化和转换
# 1. 字符串大小写转换
echo "=== Case conversion ==="
str="Hello Linux World"
echo "Original: $str"
# 转换为大写
upper=$(echo "$str" | tr '[:lower:]' '[:upper:]')
echo "Uppercase: $upper"
# 转换为小写
lower=$(echo "$str" | tr '[:upper:]' '[:lower:]')
echo "Lowercase: $lower"
# 首字母大写(简单实现)
title=$(echo "$str" | awk '{for(i=1;i<=NF;i++) $i=toupper(substr($i,1,1)) tolower(substr($i,2));}1')
echo "Title case: $title"
# 2. 字符串格式化
echo "\n=== String formatting ==="
# 使用printf格式化
name="Alice"
age=30
salary=50000
printf "Name: %s\n" "$name"
printf "Age: %d\n" "$age"
printf "Salary: $%.2f\n" "$salary"
printf "%-10s %5d %10.2f\n" "$name" "$age" "$salary"
# 3. 字符串填充和对齐
echo "\n=== String padding and alignment ==="
# 左对齐,宽度为20
printf "%-20s|\n" "Left aligned"
# 右对齐,宽度为20
printf "%20s|\n" "Right aligned"
# 居中对齐(简单实现)
center() {
local str=$1
local width=$2
local padding=$(( (width - ${#str}) / 2 ))
printf "%*s%s%*s\n" $padding "" "$str" $padding ""
}
center "Centered" 20
# 4. 数字格式化
echo "\n=== Number formatting ==="
number=1234567.89
# 千位分隔符
formatted=$(echo "$number" | awk '{printf "%\047d\n", $1}')
echo "With thousands separator: $formatted"
# 固定小数位数
formatted2=$(printf "%.2f" "$number")
echo "Two decimal places: $formatted2"
# 科学计数法
formatted3=$(printf "%e" "$number")
echo "Scientific notation: $formatted3"
# 5. 特殊字符处理
echo "\n=== Special character handling ==="
special_str="Line1\nLine2\tTabbed"
echo "With special characters:"
echo -e "$special_str"
# 转义特殊字符
escaped=$(printf "%q" "$special_str")
echo "\nEscaped: $escaped"- 运行脚本并查看结果
# 设置执行权限
chmod +x string-formatting.sh
# 运行脚本
./string-formatting.sh案例5:字符串分割和连接
目标:学习在Shell脚本中分割和连接字符串。
操作步骤:
- 创建字符串分割和连接演示脚本
# 创建脚本文件
touch string-split-join.sh
# 编辑脚本文件
vim string-split-join.sh
# 添加以下内容
#!/bin/bash
# 演示字符串分割和连接
# 1. 字符串分割
echo "=== String splitting ==="
# 使用IFS分割
str="apple,banana,cherry,date"
IFS="," read -ra fruits <<< "$str"
echo "Split by comma:"
for fruit in "${fruits[@]}"; do
echo "- $fruit"
done
# 使用awk分割
str2="Alice:25:Female"
echo "\nSplit by colon using awk:"
echo "$str2" | awk -F":" '{print "Name: " $1, "Age: " $2, "Gender: " $3}'
# 使用cut分割
echo "\nSplit by colon using cut:"
echo "$str2" | cut -d":" -f1
echo "$str2" | cut -d":" -f2
echo "$str2" | cut -d":" -f3
# 2. 字符串连接
echo "\n=== String joining ==="
# 数组元素连接
fruits_array=(apple banana cherry date)
joined=$(IFS=","; echo "${fruits_array[*]}")
echo "Joined with comma: $joined"
# 使用printf连接
joined2=$(printf "%s|" "${fruits_array[@]}")
# 移除末尾的分隔符
joined2=${joined2%|}
echo "Joined with pipe: $joined2"
# 3. 多行文本处理
echo "\n=== Multi-line text processing ==="
multi_line="Line 1\nLine 2\nLine 3\nLine 4"
echo "Original multi-line text:"
echo -e "$multi_line"
# 分割成数组
IFS=$'\n' read -ra lines <<< "$multi_line"
echo "\nSplit into array:"
for i in "${!lines[@]}"; do
echo "Line $i: ${lines[$i]}"
done
# 4. 实际应用:解析CSV数据
echo "\n=== Parsing CSV data ==="
# 模拟CSV数据
csv_data="Name,Age,City\nAlice,25,New York\nBob,30,London\nCharlie,35,Paris"
echo "CSV data:"
echo -e "$csv_data"
echo "\nParsed CSV:"
IFS=$'\n' read -ra rows <<< "$csv_data"
for i in "${!rows[@]}"; do
if [ $i -eq 0 ]; then
# 表头
IFS="," read -ra headers <<< "${rows[$i]}"
echo "Headers: ${headers[@]}"
else
# 数据行
IFS="," read -ra fields <<< "${rows[$i]}"
echo "Row $i:"
for j in "${!fields[@]}"; do
echo " ${headers[$j]}: ${fields[$j]}"
done
fi
done- 运行脚本并查看结果
# 设置执行权限
chmod +x string-split-join.sh
# 运行脚本
./string-split-join.sh案例6:高级字符串处理技巧
目标:学习一些高级的字符串处理技巧。
操作步骤:
- 创建高级字符串处理演示脚本
# 创建脚本文件
touch advanced-string.sh
# 编辑脚本文件
vim advanced-string.sh
# 添加以下内容
#!/bin/bash
# 演示高级字符串处理技巧
# 1. 正则表达式匹配
echo "=== Regular expression matching ==="
email="user@example.com"
phone="123-456-7890"
if [[ "$email" =~ ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]]; then
echo "Valid email: $email"
else
echo "Invalid email: $email"
fi
if [[ "$phone" =~ ^[0-9]{3}-[0-9]{3}-[0-9]{4}$ ]]; then
echo "Valid phone: $phone"
else
echo "Invalid phone: $phone"
fi
# 2. 字符串替换和转换
echo "\n=== Advanced string replacement ==="
# 驼峰命名转换为下划线命名
camel_case="firstName lastName"
underscore=$(echo "$camel_case" | sed 's/\([a-z0-9]\)\([A-Z]\)/\1_\2/g' | tr '[:upper:]' '[:lower:]')
echo "Camel case: $camel_case"
echo "Underscore: $underscore"
# 3. 字符串去重
echo "\n=== String deduplication ==="
duplicate_str="aaabbbcccdddeee"
deduplicated=$(echo "$duplicate_str" | sed 's/\(\(.)\)\1*/\1/g')
echo "Original: $duplicate_str"
echo "Deduplicated: $deduplicated"
# 4. 字符串反转
echo "\n=== String reversal ==="
original="Hello World"
reversed=$(echo "$original" | rev)
echo "Original: $original"
echo "Reversed: $reversed"
# 5. 单词统计
echo "\n=== Word counting ==="
text="The quick brown fox jumps over the lazy dog"
word_count=$(echo "$text" | wc -w)
echo "Text: $text"
echo "Word count: $word_count"
# 字符统计
char_count=$(echo -n "$text" | wc -c)
echo "Character count: $char_count"
# 行数统计
line_count=$(echo -e "$text\nAnother line" | wc -l)
echo "Line count: $line_count"
# 6. 字符串加密和解密(简单实现)
echo "\n=== Simple string encryption/decryption ==="
# 简单的凯撒密码
encrypt() {
local str=$1
local shift=$2
echo "$str" | tr "[a-z]" "[$((shift + 97))-z[a-${((shift + 96))]]" | tr "[A-Z]" "[$((shift + 65))-Z[A-${((shift + 64))]]"
}
decrypt() {
local str=$1
local shift=$2
encrypt "$str" $((26 - shift))
}
secret="Hello Linux"
encrypted=$(encrypt "$secret" 3)
echo "Original: $secret"
echo "Encrypted: $encrypted"
decrypted=$(decrypt "$encrypted" 3)
echo "Decrypted: $decrypted"
# 7. URL编码和解码
echo "\n=== URL encoding/decoding ==="
url="https://example.com/path with spaces?query=value"
# URL编码
encoded=$(printf '%s' "$url" | sed 's/ /%20/g; s/!/%21/g; s/"/%22/g; s/#/%23/g; s/\$/%24/g; s/&/%26/g; s/'"'"'/%27/g; s/(/%28/g; s/)/%29/g; s/\*/%2A/g; s/+/%2B/g; s/,/%2C/g; s/;/%3B/g; s/=/%3D/g; s/?/%3F/g; s/@/%40/g')
echo "Original URL: $url"
echo "Encoded URL: $encoded"
# 8. 模板替换
echo "\n=== Template replacement ==="
template="Hello {name}, you are {age} years old and live in {city}."
# 替换函数
replace_template() {
local template=$1
local name=$2
local age=$3
local city=$4
template=${template/{name}/$name}
template=${template/{age}/$age}
template=${template/{city}/$city}
echo "$template"
}
replace_template "$template" "Alice" "25" "New York"
replace_template "$template" "Bob" "30" "London"- 运行脚本并查看结果
# 设置执行权限
chmod +x advanced-string.sh
# 运行脚本
./advanced-string.sh课后练习
基础练习
- 创建一个脚本,计算字符串中单词的数量
- 编写一个脚本,将字符串转换为大写并反转
- 设计一个脚本,检查字符串是否是回文
进阶练习
- 创建一个脚本,解析日志文件中的IP地址
- 编写一个脚本,格式化电话号码为标准格式
- 设计一个脚本,从CSV文件中提取特定列的数据
挑战练习
- 编写一个脚本,实现简单的文本搜索引擎
- 创建一个脚本,解析和处理JSON格式的字符串
- 设计一个脚本,实现字符串的压缩和解压缩
总结
本集详细介绍了Linux Shell脚本中的字符串处理操作,包括字符串的基本操作、比较、查找替换、格式化、转换、分割和连接等内容。通过学习这些知识,读者可以在Shell脚本中灵活处理各种字符串操作,提高脚本的实用性和效率。
字符串处理是Shell脚本编程中的重要组成部分,它允许脚本处理和分析文本数据,实现各种文本操作和转换。掌握字符串处理技巧是编写复杂Shell脚本的基础。
通过本集的学习,读者应该能够理解和使用基本的字符串操作,掌握字符串的比较和测试方法,理解字符串的查找和替换操作,掌握字符串的格式化和拼接技巧,以及学习字符串的转换和处理方法。这些知识将为后续学习文件操作和错误处理打下基础。