✸ ✸ ✸
什么是列转行
列转行是 shell 文本处理中的常见需求:把文件中每行一个的数据,合并成一行并用指定分隔符连接。比如把一列 ID 转成逗号分隔的字符串,方便拼接 SQL 的 IN 条件。
转换前(列): 转换后(行):
123 123,456,222,3312
456
222
3312
方法一:awk printf(最常用)
# 基本用法:逗号分隔
$ cat ids.txt
123
456
222
3312
$ awk '{printf "%s,",$1}' ids.txt
123,456,222,3312,
注意末尾会多一个逗号。去掉末尾逗号的写法:
# 方法1:用 NR 判断是否第一行
$ awk 'NR>1{printf ","}{printf "%s",$1}' ids.txt
123,456,222,3312
# 方法2:用 ORS(输出记录分隔符)
$ awk '{ORS=","} {print $1}' ids.txt | sed 's/,$/\n/'
123,456,222,3312
# 方法3:先拼接再去尾
$ awk '{printf "%s,",$1}' ids.txt | sed 's/,$/\n/'
123,456,222,3312
方法二:paste 命令(最简洁)
# -s 表示串行合并,-d 指定分隔符
$ paste -sd',' ids.txt
123,456,222,3312
# 用其他分隔符
$ paste -sd'|' ids.txt
123|456|222|3312
# 空格分隔
$ paste -sd' ' ids.txt
123 456 222 3312
paste -sd',' 是最优雅的写法,没有末尾多余分隔符的问题。
方法三:tr 命令
# 将换行符替换为逗号
$ tr '\n' ',' < ids.txt
123,456,222,3312,
# 去掉末尾逗号
$ tr '\n' ',' < ids.txt | sed 's/,$/\n/'
123,456,222,3312
方法四:xargs
# 默认空格分隔
$ cat ids.txt | xargs
123 456 222 3312
# 指定分隔符(通过 sed 后处理)
$ cat ids.txt | xargs | sed 's/ /,/g'
123,456,222,3312
方法五:sed 一行流
# 用 sed 的 N 命令合并行
$ sed ':a;N;s/\n/,/;ta' ids.txt
123,456,222,3312
配合 seq 生成序列
# 生成连续数字并转为逗号分隔
$ seq 1 5 | paste -sd','
1,2,3,4,5
# 生成 ID 范围
$ seq 16396 16405 | awk '{printf "%s,",$1}'
16396,16397,16398,16399,16400,16401,16402,16403,16404,16405,
# 更优雅
$ seq 16396 16405 | paste -sd','
16396,16397,16398,16399,16400,16401,16402,16403,16404,16405
实战场景
场景1:拼接 SQL IN 条件
# 从文件中读取 ID 列表,拼成 SQL
$ cat user_ids.txt
1001
1002
1003
1004
# 生成 IN 条件(带引号,适合字符串字段)
$ awk '{printf "\x27%s\x27,",$1}' user_ids.txt | sed 's/,$//'
'1001','1002','1003','1004'
# 完整 SQL
$ echo "DELETE FROM users WHERE id IN ($(paste -sd',' user_ids.txt));"
DELETE FROM users WHERE id IN (1001,1002,1003,1004);
场景2:批量 ping 检测
# 从 IP 列表生成批量 ping 命令
$ cat ips.txt | while read ip; do
ping -c1 -W1 $ip > /dev/null 2>&1 && echo "$ip OK" || echo "$ip FAIL"
done
场景3:合并多行日志
# 将多行错误堆栈合并为一行(用 | 分隔)
grep -A5 "Exception" app.log | paste -sd'|'
反向操作:行转列
# 逗号分隔的一行转为多行
$ echo "123,456,222,3312" | tr ',' '\n'
123
456
222
3312
# 或者用 awk
$ echo "123,456,222,3312" | awk -F',' '{for(i=1;i<=NF;i++) print $i}'
123
456
222
3312
方法对比
| 方法 | 优点 | 末尾多余分隔符 | 推荐度 |
|---|---|---|---|
paste -sd',' | 最简洁 | 无 | 强烈推荐 |
awk printf | 灵活,可定制格式 | 有,需处理 | 推荐 |
tr '\n' ',' | 简单直观 | 有,需处理 | 一般 |
xargs | 默认空格分隔 | 无 | 一般 |
sed | 一行搞定 | 无 | 炫技用 |
总结
列转行首选 paste -sd',',简洁无副作用。需要复杂格式化时用 awk printf。行转列用 tr ',' '\n'。这几个命令组合起来,基本能搞定所有文本行列转换需求。
✸ ✸ ✸
📜 版权声明
本文作者:王梓 | 原文链接:https://www.bthlt.com/note/149-shell���������������������
出处:葫芦的运维日志 | 转载请注明出处并保留原文链接


📜 留言板
留言提交后需管理员审核通过才会显示