Idle Works, Idle Thoughts

Sed学习笔记

基础用法

删除空白行:

$ cat file | sed '/^$/d'

删除打头的空格或Tab:

$ cat file | sed -e 's/^[ \t]*//'   

s - substitue, 替换命令。

目标:格式化 Mac Kindle 导出的读书笔记

Mac Kindle 导出的读书笔记含有许多没有意义的空格,用Sed简化之,并将处理结果保存在剪切板(可直接粘贴于其他文本编辑器):

$ cat notetext.html | grep "noteText"|tr \' \"|sed 's#.*<div class="noteText">\(.*\)</div>#\1#g;s# ##g' | awk '{print $1, "\n"}' | pbcopy

目标:从输入行中抽取目标字段

从日志中,打印 u(USERNAME)seller(SELLER) 的内容。

150728 14:02:14 debug u(Monica) ip(111.161.77.228) # htdocs/adq.php:407:debug_log() set seller(wuyasd) level(2)

这里的关键是要全行替换,因此 pattern 要匹配整个输入行:

$ cat log.txt |sed -e 's/.*u(\(.*\)) ip.*seller(\(.*\)),.*/\1 \2/g'

目标:在每个文件的头部插入一段文本

把Markdown文件迁移到Jekyll中来,要符合Liquid模版文件的要求,即在每个文件的头部,有如下的一段配置。

---
layout: default
title: 
---

用 find 找出所有的 .md 文件,用 Sed 在每个文件的头部插入配置:

$ find ./ -name "*.md" -exec sed -i '1 i\---\nlayout: default\ntitle: \n---\n' {} \;

目标:用nil填充空白字段

现在有个文件其内容如下

foo|||bar
qux||boo|fzx

要把所有空白字段都填充为nil,如下

foo|nil|nil|bar
qux|nil|boo|fzx

用sed实现

$ sed ':a; s/||/|nil|/g; ta' t.txt 
foo|nil|nil|bar 
qux|nil|boo|fzx

:a表示打了一个标签命名为a,而ta表示跳转到标签a。在这里t表示test的意思,如果执行了替换指令,则会跳转到标签a。即修改后再次检查是否需要修改的意思。如果删除:a/ta,则第1行只执行一次替换,如下所示,是个不完整的替换:

$ sed 's/||/|nil|/g' t.txt                                 
foo|nil||bar
qux|nil|boo|fzx

如果空白字段出现在行首或行尾,则这个sed命令还无法处理。需要进一步针对2种特殊情况处理。

$ sed 's/^|/nil|/; s/|$/|nil/; :a; s/||/|nil|/g; ta' t.txt

目标:删除文本中的\n

Sed是以行为单位编辑文本的。因此要删除\n不能直接删,如:

$ head -n3 gdu.html | sed 's/\n//g'    
<html>
  <head>
    <meta charset="utf8" />

正确的删除方法如下:

$ head -n3 gdu.html | sed ':a;N;$!ba;s/\n//g'
<html>  <head>    <meta charset="utf8" />

说明:

前面这几个命令的作用是把整个文件都放入一个模式空间中去,之后再把\n替换为空,即s/\n//g这部分的工作。

其他解决办法

Bash:

$ head -n3 gdu.html | while read line; do printf "%s" "$line"; done; echo
<html><head><meta charset="utf8" />

Perl:

$ head -n3 gdu.html | perl -p -e 's/\n//'; echo
<html>  <head>    <meta charset="utf8" />

tr:

$ head -n3 gdu.html | tr '\n' ' '; echo 
<html>   <head>     <meta charset="utf8" />

paste:

$ head -n3 gdu.html | paste -s -d ' '
<html>   <head>     <meta charset="utf8" />

awk:

$ head -n3 gdu.html |awk 1 ORS=' '; echo
<html>   <head>     <meta charset="utf8" />