ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Linux seq命令详解:从基础语法到实战脚本案例

Linux seq命令详解:从基础语法到实战脚本案例 1. 为什么需要 seq 命令先来思考一个很常见的场景我们在写 Shell 脚本时经常需要生成一串连续的序号。例如批量创建带编号的文件、循环执行某个操作 10 次、生成从 1 到 100 的数字列表。很多新手第一反应是手动敲1 2 3 4 5 6 7 8 9 10。如果数字范围小倒还好一旦需要生成 1 到 1000 的序列手动输入就不现实了。这时 Linux 提供了一个非常简洁的解决方案——seq命令。seq的全称是sequence中文意思是“序列”。它的核心作用就是根据用户给定的起始值、结束值和步长生成一串数字序列并在标准输出中打印出来。seq命令虽小却是 Shell 编程中非常实用的基础工具。掌握它之后你可以配合for循环实现指定次数的批量操作快速生成测试数据或文件名后缀在脚本中控制循环范围避免写死列表生成倒序数字序列按指定格式输出带前导零或自定义分隔符的序列。本文将以实践为主线系统讲解seq命令的基础用法、参数细节、实战案例和踩坑经验。无论你是刚接触 Linux 的新手还是想巩固 Shell 脚本功底的开发者都能从中获得可复用的技巧。需要说明的是本文示例以 CentOS 7 和 Ubuntu 20.04 等常见 Linux 发行版环境为主重点演示命令的写作思路和适用场景。不同发行版中的seq命令实现略有差异但核心参数基本一致。2. 基础语法与参数详解seq命令的语法并不复杂先来看它的三种基本形式。seq LAST seq FIRST LAST seq FIRST INCREMENT LAST第一种形式seq LAST表示从 1 开始以步长 1 递增一直输出到 LAST。第二种形式seq FIRST LAST表示从 FIRST 开始以步长 1 递增输出到 LAST。第三种形式则显式指定了起始值、步长和结束值。先看几个最简单直观的例子。# 输出 1 到 5 的数字 seq 5执行结果如下1 2 3 4 5再看指定起始值和结束值的情况# 输出 3 到 8 的数字 seq 3 8执行结果如下3 4 5 6 7 8最后看指定步长的用法# 从 1 开始每次增加 2直到大于 10 停止 seq 1 2 10执行结果如下1 3 5 7 9注意seq 1 2 10的输出在 9 就结束了因为再加 2 会变成 11超过结束值 10所以不会输出。这一点在写循环时要格外留意。2.1 三个位置参数的含义从上面的例子可以看出seq命令通常接收三个位置参数第一个参数序列的起始值第二个参数步长也可以理解为每次递增或递减的量第三个参数序列的结束值。当只有一个参数时起始值默认为 1步长默认为 1。当只有两个参数时第一个参数是起始值第二个参数是结束值步长默认为 1。这个规律非常容易记忆。2.2 支持正数、负数和浮点数seq命令不仅仅支持正整数也支持负数和浮点数。来看几个例子。# 从 5 倒数到 1 seq 5 -1 1执行结果如下5 4 3 2 1再来看浮点数的用法# 生成 0 到 1 之间、步长为 0.2 的浮点序列 seq 0 0.2 1执行结果如下0 0.2 0.4 0.6 0.8 1.0这里有一个细节需要注意浮点数运算在计算机中可能存在精度误差比如某些组合下输出 0.999999 而不是 1.0。在需要高精度计算的场景中建议先确认你的 Linux 发行版中seq命令的具体表现或者改用其他更精确的工具。2.3 通过 -s 参数指定分隔符默认情况下seq输出的每个数字占一行。但实际工作中我们也经常需要把序列拼接在一行用自定义分隔符隔开。-s参数就是用来指定分隔符的。# 使用空格作为分隔符 seq -s 1 5输出结果如下1 2 3 4 5再看一个更常见的业务场景生成逗号分隔的数字列表方便直接粘贴到 SQL 语句或配置文件中。# 使用逗号作为分隔符 seq -s , 1 5输出结果如下1,2,3,4,5-s参数还可以接受更多自定义字符比如-s -或-s |。需要注意的是如果分隔符本身包含特殊字符建议用单引号或双引号包裹避免 Shell 解析出错。2.4 通过 -w 参数等宽输出在某些需要对齐的场景中我们希望输出的数字具有相同的宽度不足位用 0 补全。-w参数可以自动根据最大值补前导零。# 等宽输出 1 到 10 seq -w 1 10输出结果如下01 02 03 04 05 06 07 08 09 10如果最大值是 100那么 1 到 9 都会补成 001、002…… 这种等宽格式非常适合文件名排序。例如批量生成图片文件名img_001.jpg如果不补前导零排序时img_10.jpg会排在img_9.jpg前面导致顺序错乱。2.5 通过 -f 参数自定义格式-f参数比-w更灵活可以完全自定义输出格式。它使用类似 C 语言printf的格式字符串。# 输出 1 到 5并在数字前加序号前缀 seq -f item_%g 1 5输出结果如下item_1 item_2 item_3 item_4 item_5格式字符串中的%g是占位符代表当前生成的数字。除此之外%e表示科学计数法%f表示浮点数。来看两个例子。# 以带两位小数的浮点数形式输出 seq -f %.2f 1 2 5输出结果如下1.00 3.00 5.00# 以科学计数法输出 seq -f %e 1 2 3输出结果如下1.000000e00 3.000000e00在实际项目中-f参数常用于生成日志文件名、带批次编号的目录、或符合特定格式的上报数据。2.6 快速生成倒序序列在很多需要倒序处理的场合seq也能派上用场。核心思路是让起始值大于结束值同时把步长设置为负数。# 从 10 递减到 1 seq 10 -1 1输出结果如下10 9 8 7 6 5 4 3 2 1但需要注意如果步长不写只写seq 10 1那么seq会认为这是“从 10 到 1步长为 1”此时由于 10 大于 1按正方向增加永远不会到达 1最终不会输出任何内容。这种隐蔽的问题在脚本中很容易踩坑需要特别留意。3. 实战案例前面讲解了seq的基础语法和核心参数这一节通过几个完整的实战案例演示如何把seq与 Shell 脚本结合解决实际开发中的问题。3.1 案例一批量创建编号文件运维或后端开发中经常需要批量生成日志文件或数据文件。假设我们要创建test_01.txt到test_10.txt共 10 个文件使用seq与for循环可以轻松实现。#!/bin/bash # 文件路径create_files.sh for i in $(seq -w 1 10) do touch test_${i}.txt done echo 文件创建完成 ls -l test_*.txt这里使用seq -w 1 10生成01 02 03 ... 10的等宽序列再通过变量拼接文件名。执行脚本后当前目录下会生成 10 个文件名称分别是test_01.txt、test_02.txt……test_10.txt。由于文件名中带前导零ls排序时顺序也是正确的。3.2 案例二批量执行命令行工具假设我们有一个数据处理脚本process_data.sh每次接收一个参数表示处理第几批数据。我们需要连续执行 5 次分别传入参数 1 到 5。#!/bin/bash # 文件路径batch_process.sh for n in $(seq 5) do echo 正在处理第 ${n} 批数据... bash process_data.sh $n done先输出提示信息再调用实际的数据处理脚本。这样做的好处是如果某一次执行失败我们可以根据输出的n值快速定位到是第几批数据出问题。这种方法在批量跑数、批量上传文件时非常常用。3.3 案例三生成 SQL 批量更新语句在数据修复或测试数据插入场景中经常需要生成大量的 SQL 语句。假设我们要把某张表中的status字段从 0 更新为 1记录 id 从 1 到 200。手动写 SQL 不现实而使用seq可以快速生成。#!/bin/bash # 文件路径generate_sql.sh for id in $(seq 1 200) do echo UPDATE user_table SET status 1 WHERE id ${id}; done执行后屏幕上会输出 200 条UPDATE语句。我们可以用重定向把结果保存到.sql文件中bash generate_sql.sh update_status.sql然后先检查生成的文件内容确认无误后再在数据库客户端中执行。这里就体现了先审查后执行的安全意识。需要强调一点直接在生产环境批量执行 UPDATE 或 DELETE 语句风险较高务必先在测试库验证并提前备份数据。3.4 案例四制作数字选择菜单在 Shell 交互式脚本中seq可以配合select或case生成一个有序的选择菜单。#!/bin/bash # 文件路径menu.sh echo 请选择要执行的模块 for i in $(seq 1 4) do echo $i) 模块$i done read -p 请输入数字选择 choice case $choice in 1) echo 你选择了模块1 ;; 2) echo 你选择了模块2 ;; 3) echo 你选择了模块3 ;; 4) echo 你选择了模块4 ;; *) echo 无效选择 ;; esac实际运行效果如下请选择要执行的模块 1) 模块1 2) 模块2 3) 模块3 4) 模块4 请输入数字选择如果后续模块数量增加只需要修改seq后面的数字和case中的分支即可不需要手动重写菜单列表。3.5 案例五用 seq 生成测试数据有时候接口联调或性能测试需要一批模拟数据。假设要生成 10 个手机号这里仅做演示实际测试请使用合法的测试号段避免骚扰真实用户可以用seq快速组合。#!/bin/bash # 文件路径generate_phone.sh for n in $(seq -w 1 10) do echo 1380000${n} done输出结果如下13800001 13800002 13800003 13800004 13800005 13800006 13800007 13800008 13800009 13800010这种方式对于生成测试数据、构造请求参数非常高效。3.6 案例六在 awk 和 xargs 中使用 seqseq常常和其他命令配合使用构成高可复用的 Shell 任务链。# 删除 30 天前的日志文件先列出再人工确认 seq 1 5 | xargs -I {} echo 示例处理第 {} 个文件输出结果如下示例处理第 1 个文件 示例处理第 2 个文件 示例处理第 3 个文件 示例处理第 4 个文件 示例处理第 5 个文件再比如我们需要对多个端口进行连通性测试for port in $(seq 8000 8005) do timeout 1 bash -c echo /dev/tcp/127.0.0.1/${port} 2/dev/null \ echo 端口 ${port} 开放 \ || echo 端口 ${port} 未开放 done这段脚本会检查本机 8000 到 8005 端口是否开放。/dev/tcp是 Bash 的特殊伪设备配合timeout可以防止探测时长时间卡住。日常排查端口问题时这类脚本非常实用。4. seq 与其他序列工具对比在 Linux 中生成序列的方法不止seq一种。常见的有大括号展开Brace Expansion、for循环的 C 风格写法和awk。为了帮读者理解我把常见方式整理成一个对比表格。方式示例优点缺点seqseq 1 5支持变量、浮点数、步长、自定义格式需要调用外部命令大括号展开{1..5}语法简洁不需要外部命令只支持整数且变量展开不如 seq 方便C 风格 forfor ((i1; i5; i))原生命令性能好支持复杂条件写法相对冗长awkawk BEGIN{for(i1;i5;i) print i}功能强大适合生成后直接处理对新手不够直观在实际工作中选择哪种方式取决于场景如果只是生成简单的整数序列并且范围是字面量使用大括号展开{1..5}最简单。如果范围来自变量或需要指定步长、小数、输出格式seq更合适。如果循环体内有条件判断和累计运算C 风格for更灵活。来看一个对比示例。# 变量范围使用大括号展开的坑 end5 echo {1..$end}执行结果并不会输出1 2 3 4 5而是输出{1..5}因为大括号展开发生在变量替换之前Shell 把$end当成了普通字符串。而seq不存在这个问题end5 seq 1 $end这样就能正确输出1 2 3 4 5。所以当结束值来自变量时优先使用seq。5. 常见错误与排查思路掌握了seq的常见用法之后我们再来看几个新手容易遇到的问题。如果运行结果和预期不一致可以对照下表快速定位。问题现象常见原因解决思路输入seq 10 1没有输出没有指定负步长10 到 1 按正方向无法收敛使用seq 10 -1 1浮点数输出出现 0.999999 这种精度问题浮点数二进制表示产生误差使用printf格式化或awk处理{1..$n}变量操作不生效大括号展开发生在变量替换之前改用seq 1 $nseq -s, 1 5报错分隔符中的逗号或特殊字符未被正确解析使用引号包裹如seq -s , 1 5文件名排序乱序没有使用等宽输出数字前未补零使用seq -w或seq -f %02g在旧版系统上无法使用seq某些最小化安装或特殊发行版未包含使用awk或大括号展开替代5.1 为什么 seq 10 1 不输出内容很多新手第一次用seq 10 1时会觉得它应该输出 10 到 1 的倒序数字。但实际seq 的语法是seq FIRST INCREMENT LAST当只写两个参数时第二个参数被解释为 LAST而 INCREMENT 默认为 1。因此seq 10 1 等价于“从 10 开始每次加 1直到 1”永远无法达到目标所以输出为空。正确写法是显式指定负步长seq 10 -1 1这个细节也提示我们使用seq前最好先确认每个参数的含义尤其在写自动化脚本时要格外小心。5.2 浮点数精度异常浮点数在计算机中存储时本身就存在精度问题。seq底层使用类似 C 语言的浮点运算因此在大范围浮点数序列中可能出现误差。举个例子seq 0 0.1 1在某些环境中输出如下0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0这是看似正常的情况。但在另一些版本中可能输出1.0或0.999999原因就是浮点数累加产生的误差。如果需要高精度控制建议改用awkawk BEGIN { for (i0; i10; i) printf %.1f\n, i/10 }5.3 变量范围与大括号括号的冲突在编写脚本时如果用户输入的是一个变量我们要注意大括号展开的局限性。大括号展开的时机非常早早于变量替换因此{1..$n}不会按预期工作。这一点在之前已经说明。为了避免踩坑优先使用seq。5.4 seq 在某些系统上不可用虽然绝大多数主流 Linux 发行版都自带了seq但在部分极简环境或特殊嵌入式系统中这个命令可能不存在。这时可以通过awk实现类似效果awk BEGIN { for (i1; i5; i) print i }所以如果你的脚本需要跨平台运行建议在脚本开头做一个命令检测或者统一使用 POSIX 兼容性更好的awk方案。6. 最佳实践与工程建议接下来总结一下在实际项目中使用seq的工程建议避免因小失大。6.1 优先使用引号包裹变量参数seq接收的参数如果来自用户输入或变量应始终使用双引号包裹。end100 seq 1 $end这样即使变量值为空或包含空格也不会导致命令被意外拆分。虽然数字通常不会有空格但养成加引号的习惯能减少很多 Shell 脚本的安全隐患。6.2 生成文件名时使用等宽序列如果需要批量生成文件并希望排序正确使用-w或-f补零。否则file_10.txt会排在file_2.txt前面这不是我们期望的结果。# 推荐 for i in $(seq -w 1 20) do touch file_${i}.txt done6.3 避免在循环中重复执行 seq很多人会把seq直接写在for循环头部。对于少量数据这没有问题但如果循环次数非常多可以考虑一次性把序列存到变量中只生成一次。# 不推荐 for i in $(seq 1 100000) do echo $i done # 可读性更好的写法 seq 1 100000 | while read i do echo $i done不过也要注意管道会创建子 Shell在子 Shell 中修改的变量无法反馈到父 Shell。如果需要修改外部变量考虑改用进程替换或 C 风格 for 循环。6.4 脚本中设置 set -e 防止意外执行在包含seq和删除、更新等危险操作的脚本中建议在脚本开头加上set -e这样如果任何一条命令返回非零状态脚本会立即退出而不是继续执行后续的危险命令。#!/bin/bash set -e for i in $(seq 1 5) do echo 删除文件 test_${i}.txt rm -f test_${i}.txt done6.5 注意最小权限原则如果脚本以 root 身份运行并且使用了seq来批量执行操作一定要非常谨慎。例如刚才提到的批量 UPDATE 数据库语句建议先在测试库验证使用最小权限账号执行。删除文件类的操作可以先打印出将要删除的文件列表人工确认无误后再真正执行。6.6 与大括号展开、并发执行结合时的注意点在写并发任务时有人会用seq配合xargs -P实现并行处理。例如seq 1 10 | xargs -P 5 -I {} bash -c echo 处理第{}个任务这样可以同时运行 5 个任务提高效率。但要注意并发数不要设置过大否则可能导致系统资源耗尽。同时并发任务中涉及日志输出时建议打印任务的编号方便排查问题。7. 进一步学习方向seq是一个基础命令但它串联起了 Shell 脚本中“序列生成—循环—批处理”这条主线。如果读者想进一步学习可以从以下方向继续深入掌握for、while、until三种循环结构的区别理解在不同场景下如何选择。学习xargs的各种参数特别是-P并行执行如何与seq配合。熟悉printf格式化输出它是seq -f底层能力的基础。理解管道和子 Shell 的关系避免在管道循环中修改变量失效的坑。掌握awk和sed的基本用法它们是 Linux 文本处理的两大利器。seq只是进入 Shell 脚本世界的一小步。真正让脚本变强大的是把这些小命令组合起来形成完整的数据处理流程。建议读者在本地 Linux 虚拟机或云服务器上动手练习把本文的每个示例都亲手跑一遍再尝试改造成自己的脚本。动手实践之后你会发现这些命令的灵活程度远超预期。
返回列表