Shell脚本技巧:去除文件中字符串两端空白

在 Bash 脚本中,处理文件时经常需要清理每行两端的空白字符(包括空格、制表符、换行符等),类似于 Python 的 strip() 方法。虽然 Bash 没有直接内置函数实现这一功能,但可以通过内置功能和外部工具(如 sedawk、参数扩展等)实现。本文将详细介绍几种常用方法,深入剖析其工作原理,并提供代码示例。


方法 1:使用 sed 命令

代码示例

bash 复制代码
sed 's/^[[:space:]]*\|[[:space:]]*$//g' input.txt > output.txt

原理

  • sed:流编辑器(Stream Editor),逐行读取文件并应用指定的编辑命令。
  • s/pattern/replacement/g :替换命令,s 表示替换,pattern 是要匹配的内容,replacement 是替换结果(这里为空),g 表示全局替换。
  • ^[[:space:]]*
    • ^:匹配行首。
    • [[:space:]]:POSIX 字符类,匹配所有空白字符(空格、制表符、换行符等)。
    • *:表示零个或多个匹配,匹配行首的所有连续空白字符。
  • \|:正则表达式中的"或"操作符,连接两个模式。
  • [[:space:]]*$
    • $:匹配行尾。
    • [[:space:]]*:匹配行尾的所有连续空白字符。
  • //:将匹配的空白替换为空字符串。
  • > output.txt:将处理结果重定向到新文件。

执行过程

假设 input.txt 内容为:

复制代码
  Hello World  
	Tab Test	
  1. sed 逐行读取。
  2. 第一行 " Hello World "
    • 匹配开头 " ",替换为空。
    • 匹配结尾 " ",替换为空。
    • 输出:Hello World
  3. 第二行 " Tab Test "
    • 匹配开头 " "(制表符),替换为空。
    • 匹配结尾 " ",替换为空。
    • 输出:Tab Test

优点与适用场景

  • 优点:支持正则表达式,处理多种空白字符,适合批量文件操作。
  • 场景:清理日志文件或格式化文本数据。

方法 2:使用 awk 命令(王炸)

代码示例

bash 复制代码
awk '{$1=$1};1' input.txt > output.txt

原理

  • awk:文本处理工具,按行处理文件,默认以空白字符(空格、制表符等)作为字段分隔符。
  • {$1=$1}
    • $1:表示当前行的第一个字段。
    • =$1:将第一个字段重新赋值给自身。
    • 关键机制awk 在重新赋值时,会重新构建整行,自动去除行首和行尾的空白字符,同时将字段间的多个空白压缩为单个空格。
  • 1
    • awk 中,条件为真(非零)时打印整行。
    • 这里 1 恒为真,等价于 {print $0},输出处理后的行。
  • > output.txt:将结果重定向到新文件。

执行过程

假设 input.txt 内容为:

复制代码
  Hello   World  
	Tab	Test	
  1. 第一行 " Hello World "
    • $1="Hello"$2="World"
    • 重新构建:Hello World(两端空白被移除,中间多余空格压缩为一个)。
    • 输出:Hello World
  2. 第二行 " Tab Test "
    • $1="Tab"$2="Test"
    • 重新构建:Tab Test
    • 输出:Tab Test

优点与适用场景

  • 优点:代码简洁,自动处理所有空白字符,效率高。
  • 场景:快速清理简单文本文件,尤其是字段分隔明确的内容。

注意

  • 如果行中只有空白字符,输出为空行。

方法 3:使用 Bash 参数扩展与 while read

代码示例

bash 复制代码
while read -r line; do
  trimmed="${line#"${line%%[![:space:]]*}"}"
  trimmed="${trimmed%"${trimmed##*[![:space:]]}"}"
  echo "$trimmed"
done < input.txt > output.txt

原理

  • while read -r line
    • read -r:逐行读取文件内容,-r 防止反斜杠转义。
    • < input.txt:将文件内容重定向到循环。
  • "${line#"${line%%[![:space:]]*}"}"
    • ${line%%[![:space:]]*}:从 $line 末尾开始,匹配最短的非空白字符之前的部分(即开头的所有空白)。
    • ${line#...}:从 $line 开头移除匹配的部分。
    • 结果:去掉行首空白。
  • "${trimmed%"${trimmed##*[![:space:]]}"}"
    • ${trimmed##*[![:space:]]}:从 $trimmed 开头开始,匹配最长的非空白字符之后的部分(即结尾的所有空白)。
    • ${trimmed%...}:从 $trimmed 结尾移除匹配的部分。
    • 结果:去掉行尾空白。
  • echo "$trimmed":输出处理后的行。
  • > output.txt:将结果重定向到新文件。

执行过程

假设 input.txt 内容为:

复制代码
  Hello World  
	Tab Test	
  1. 第一行 " Hello World "
    • ${line%%[![:space:]]*} 匹配 " ",移除后得 "Hello World "
    • ${trimmed##*[![:space:]]} 匹配 " ",移除后得 "Hello World"
    • 输出:Hello World
  2. 第二行 " Tab Test "
    • ${line%%[![:space:]]*} 匹配 " ",移除后得 "Tab Test "
    • ${trimmed##*[![:space:]]} 匹配 " ",移除后得 "Tab Test"
    • 输出:Tab Test

优点与适用场景

  • 优点:无需外部工具,纯 Bash 实现,适合变量处理或小文件。
  • 场景:需要逐行处理并结合其他逻辑时。

注意

  • 对大文件性能较低,因逐行读取和处理较慢。

方法 4:使用 trsed 组合

代码示例

bash 复制代码
tr -s '[:space:]' < input.txt | sed 's/^[[:space:]]*\|[[:space:]]*$//g' > output.txt

原理

  • tr -s '[:space:]'
    • -s:压缩(squeeze),将连续的空白字符替换为单个空白。
    • '[:space:]':匹配所有空白字符。
    • 作用:将行内多余空白压缩,但无法直接去除两端空白。
  • sed 's/^[[:space:]]*\|[[:space:]]*$//g'
    • 与方法 1 相同,去除行首和行尾的空白。
  • 管道tr 处理后输出到 sed,再重定向到文件。

执行过程

假设 input.txt 内容为:

复制代码
  Hello   World  
	Tab	Test	
  1. 第一行 " Hello World "
    • tr -s" Hello World "
    • sed"Hello World"
    • 输出:Hello World
  2. 第二行 " Tab Test "
    • tr -s" Tab Test "
    • sed"Tab Test"
    • 输出:Tab Test

优点与适用场景

  • 优点:结合两工具优势,处理复杂空白情况。
  • 场景:需要同时压缩行内空白并去除两端空白。

总结与选择建议

方法 原理核心 优点 缺点 适用场景
sed 正则替换 灵活,支持多种空白 需熟悉正则 批量清理
awk 字段重新构建 简洁,效率高 行内空白压缩 简单文本处理
参数扩展+read 字符串模式匹配 无外部依赖 性能低,语法复杂 小文件或变量处理
tr+sed 压缩+正则替换 处理复杂空白 多步骤 行内+两端清理
  • 快速批量处理 :推荐 sedawk
  • 小文件或变量:使用参数扩展。
  • 复杂空白清理 :结合 trsed
相关推荐
world-wide-wait5 小时前
python高级04——网络编程
linux·服务器·网络
迎風吹頭髮5 小时前
Linux内核架构浅谈26-Linux实时进程调度:优先级反转与解决方案
linux·服务器·架构
Java 码农5 小时前
CentOS 7上安装SonarQube10
linux·centos
特种加菲猫5 小时前
网络协议分层:解密TCP/IP五层模型
linux·网络·笔记
平平无奇。。。5 小时前
版本控制器之Git理论与实战
linux·git·gitee·github
宇宙第一小趴菜5 小时前
11 安装回忆相册
linux·运维·centos7·yum·回忆相册·kh_mod
艾莉丝努力练剑5 小时前
【Linux指令 (二)】不止于入门:探索Linux系统核心与指令的深层逻辑,理解Linux系统理论核心概念与基础指令
linux·服务器·数据结构·c++·centos
conkl6 小时前
Linux IP 网络配置与管理详解
linux·网络·tcp/ip
ZhiqianXia6 小时前
Linux 内核中控制调试输出的频率和次数
linux