SED的典型应用

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SED的典型应用相关的知识,希望对你有一定的参考价值。

参考技术A

SED的典型用法:Sed接受一个或多个编辑命令,并且每读入一行后就依次应用这些命令。
当读入第一行输入后,sed对其应用所有的命令,然后将结果输出。接着再读入第二行输入,对其应用所有的命令……并重复这个过程。上一个例子中sed由标准输入设备(即命令解释器,通常是以管道输入的形式)获得输入。在命令行给出一个或多个文件名作为参数时,这些文件取代标准输入设备成为sed的输入。sed的输出将被送到标准输出(显示器)。因此:
cat filename | sed '10q' # 使用管道输入
sed '10q' filename # 同样效果,但不使用管道输入
sed '10q' filename > newfile # 将输出转移(重定向)到磁盘上
要了解sed命令的使用说明,包括如何通过脚本文件(而非从命令行)来使用这些命令。
要发掘sed的潜力,则必须对“正则表达式”有足够的理解 。
Unix系统所提供的手册页(“man”)也会有所帮助(试一下这些命令“man sed”、“man regexp”,或者看“man ed”中关于正则表达式的部分),但手册提供的信息比较“抽象”——这也是它一直为人所诟病的。不过,它本来就不是用来教初学者如何使用sed或正则表达式的教材,而只是为那些熟悉这些工具的人提供的一些文本参考。

从 ini 文件的某些部分读取某些键(sed/awk?)

【中文标题】从 ini 文件的某些部分读取某些键(sed/awk?)【英文标题】:Read certain key from certain section of ini file (sed/awk ?) 【发布时间】:2014-04-28 07:39:19 【问题描述】:

我需要从具有典型结构的 ini 文件中检索键的值:

[abcd]
key1=a
key2=b
[efgh]
key1=c
key2=d
[hijk]
key1=e
key2=f

键名在不同部分重复,并且部分的命名/顺序不一致。我怎样才能从 efgh 找到 key1?如果我使用 grep,我会找到所有 key1(而且我不知道这些部分的顺序)。

我怀疑 sed 或 awk 可以做到这一点,但我找不到它......

【问题讨论】:

【参考方案1】:

这可能是一个开始:

awk -F'=' -v section="[efgh]" -v k="key1"  '
$0==section f=1; next   # Enable a flag when the line is like your section
/\[/ f=0; next          # For any lines with [ disable the flag
f && $1==k print $0     # If flag is set and first field is the key print key=value
' ini.file

您传递了两个变量,sectionksection 需要包含您要查看的部分。 k 应该包含您试图为其获取价值的 key

[efgh] 部分下查找key1 的值:

$ awk -F'=' -v section="[efgh]" -v k="key1"  '
$0==section f=1; next   
/\[/ f=0; next          
f && $1==k print $0       
' ini.file
key1=c

[hijk] 部分下查找key2 的值:

$ awk -F'=' -v section="[hijk]" -v k="key2"  '
$0==section f=1; next   
/\[/ f=0; next          
f && $1==k print $0       
' ini.file
key2=f

【讨论】:

@Michelle 你能详细说明什么不起作用吗?错误?什么都没找到?在您的问题中发布相关数据集。这只是打印值。你想要整个key=value 对吗?【参考方案2】:

使用 sed

sed -r ':a;$!N;ba;s/.*\[efgh\][^[]*(key1=[^\n]*).*/\1/' file

key1=c

另一种方式

sed -nr '/\[efgh\]/,/\[//key1/p' file

【讨论】:

像这样吞食整个文件可能不是一个好主意。 好建议,第二个怎么样?我是根据@Guru 的想法制作的。 抱怨 Perl 不可读的人应该尝试 sed ... :-)。但是,第二个示例中的反斜杠迷宫完美地满足了我的要求!【参考方案3】:

一种方式:

sed -n '/\[efgh\]/,/\[.*\]/p' file | awk -F= '/key2/print $2'

使用 sed,提取从 [efgh] 到下一个 [....] 模式的行范围。使用awk,在这行范围内搜索key2,得到值。

【讨论】:

你实际上可以通过 sed -nr '/\[efgh\]/,/\[.*\]//key1/s/(.*)=(.*)/\2/p' file 避免 awk【参考方案4】:

这些sed 单线为我工作,无耻地从github:thomedes/ini.sed 复制

#  List all [sections] of a .INI file
sed -n 's/^[ \t]*\[\(.*\)\].*/\1/p'

#  Read KEY from [SECTION]
sed -n '/^[ \t]*\[SECTION\]/,/\[/s/^[ \t]*KEY[ \t]*=[ \t]*//p'

#  Read all values from SECTION in a clean KEY=VALUE form
sed -n '/^[ \t]*\[SECTION\]/,/\[/s/^[ \t]*\([^#; \t][^ \t=]*\).*=[ \t]*\(.*\)/\1=\2/p'

# examples:
sed -n 's/^[ \t]*\[\(.*\)\].*/\1/p' /etc/samba/smb.conf
sed -n '/^[ \t]*\[global\]/,/\[/s/^[ \t]*workgroup[ \t]*=[ \t]*//p' /etc/samba/smb.conf
sed -n '/^[ \t]*\[global\]/,/\[/s/^[ \t]*\([^#; \t][^ \t=]*\).*=[ \t]*\(.*\)/\1=\2/p' /etc/samba/smb.conf

【讨论】:

【参考方案5】:

这可能对你有用(GNU sed):

sed -rn '/^\[/h;d;G;s/^key1=(.*)\n\[efgh\]$/\1/p' file

复制节标题并将其与节正文进行比较。

【讨论】:

以上是关于SED的典型应用的主要内容,如果未能解决你的问题,请参考以下文章

sed正则表达式的使用以及使用sed修改配置文件的典型案例

sed正则表达式的使用以及使用sed修改配置文件的典型案例

第3章 机器学习的典型应用 3-2 典型应用-聚类

第3章 机器学习的典型应用 3-1 典型应用-关联规则

第3章 机器学习的典型应用 3-3 典型应用-朴素贝叶斯和决策树

裴礼文数学分析中的典型问题与方法第5章级数练习