Calcifer Calcifer 2
Linux

shell列转行加分隔符

2016/11/04 16:15 6291 次阅读 王梓
打赏
✸ ✸ ✸

什么是列转行

列转行是 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���������������������

出处:葫芦的运维日志 | 转载请注明出处并保留原文链接

📜 留言板

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