Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2349298
  • 博文数量: 527
  • 博客积分: 10343
  • 博客等级: 上将
  • 技术积分: 5565
  • 用 户 组: 普通用户
  • 注册时间: 2005-07-26 23:05
文章分类

全部博文(527)

文章存档

2014年(4)

2012年(13)

2011年(19)

2010年(91)

2009年(136)

2008年(142)

2007年(80)

2006年(29)

2005年(13)

我的朋友

分类: LINUX

2009-12-24 01:12:08

1. 虽然直观的办法是通过替换, 但最佳的工具应是tr

echo $'1\n2\n3\n4\n5' | tr -d $'\r\n'
如果输入源是文件, 注意不能把文件名摆在tr的最后, 要用
tr -d $'\r\n' < filename.txt
这种形式.

优点: 内存占用小, 快速, 对大文件友好.
缺点: 无

2. sed往往是冲动之下的第一个选择, 但对眼下的活计它绝非上选:
echo $'1\n2\n3\n4\n5' | sed -n $':n $!N;s/\\\n//g;tn;p'
它涉及到了绝大多数情况下都不会用到的sed 最阴暗角落里不为人知的技巧.
:n 定义一个label就够变态. 还要用tn 来有条件地跳转到这个label. 条件是只在前面的命令s成功发生替换时.
s 的写法也绝不友好, 那个\\\n 是必需的, 在$'' 之下, 第一对\\变成了一个转义符: \, 而第二个\n变成了结结实实的一个ASCII为10的换行符(\n), 换行符之前需要转义, 所以多出来两个\\. 这个替换会把当前pattern 空间中最后的那个\n给删除掉, 也就是说, 对于输入 "1\n2\n3\n", 最后一个\n之外的其它\n会被删除掉. 但最后的那个钉子户, 你是拔不掉的, 虽然, 你也许已经注意到了那个g标志(在这个方案里属于多余). 在最后一行时, t将会失败, 所以不再跳转到label n处, 最后的那个 p得以执行, 所有内容最终显示出来. 但是, 最末尾是有一个\n的.


上面特意安插了额外p命令之后, 可以兀显整个处理过程:
第1步: $!N, 在读取第1行之后, 因为不是最后一行, 所以读取下一行内容, 此时pattern中内容有2行

第2步: p1 执行, 显示了pattern空间中A, B两行的内容, 被显示的内容是有\n的.
第3步: s命令把"1\n2\n" 的内容替换为"12\n"
第4步: p2 执行, 显示s处理之后的pattern 空间中的新内容: "12\n"(C行) 这是C行的内容
第5步: 因为第3步中s命令成功执行, tb命令把处理流程转到标号b处.

下一个循环中,
第1步: $!N, 读取第3行, pattern中内容为"12\n3\n"
第2步: p1执行, 显示内容为"12\n3\n"(D, E行)
第3步: s命令成功执行, 把pattern空间中的内容替换为"123\n"
第4步: p2执行, 显示"123\n"(F行)
第5步: 因为前面第3步s替换成功, 所以转到标号b处.

再一个循环中:
第1步: $!N, 因为已经处于最后一行, 所以读取不到额外内容了, pattern空间中内容保持不变, 为"123\n"
第2步: p1执行, 显示"123\n"(G行)
第3步: s命令把"123\n" 替换后, 内容不变, 仍为"123\n", 视为替换不成功
第4步: p2执行, 显示"123\n"(H行)
第5步: 由于第3步s命令失败, 不执行tn跳转, 进行下一个命令:

第6步: p, 显示整个pattern中的内容为"123\n"(I行), 注意最后那个\n挥之不去.

优点: 无论如何还算可行
缺点: 写法复杂, 需要多次try/error, 对大文件不友好, 整个文件内容全部放入缓冲区.

最后, 一个可能的变体:
echo $'1\n\r2\n3\n4\n5' |sed -n $':n $!{N;bn;};s/\\\n\|\\r//gp'
在执行时会比前者快, 因为执行s替换命令只有一次. 而且上述命令也支持DOS/MAC格式的文件.

3. paste

paste -d "" -s readme.txt
优点: 简单
缺点: 不容易想到, 只适用unix格式的文本文件, 对\r\n, 或\n\r(MAC)不行

4. od -t x1 readme.txt | sed 's/^[0-9]*\b//;s/\b0a\b//g;s/ //g'  | xxd -r -ps

od -t x1 的输出中, 最开头是7个数字的地址, 第一个s/^[0-9]*\b// 把地址部分去掉, 第二个s/\b0a\b//g 把换行符去掉. 第三个s/ //g 是把所有空格去掉. 最后用xxd -r -ps把hex string转回来显示.

优点: 容易扩展为处理DOS/MAC格式的文件. 步骤分明, 容易理解.
缺点: 不容易想到.

阅读(1409) | 评论(2) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2010-01-06 00:29:01

好文!

chinaunix网友2010-01-06 00:29:01

好文!