关于shell编程(3):awk中的sub和gsub

本文详细介绍了awk命令中sub和gsub函数的区别与用法。sub用于替换记录或指定域中首次匹配到的字符串,而gsub则替换所有匹配项。通过具体示例展示了不同参数配置下两者的操作效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

subgsub的区别

awk '{sub(/aa/,"cc");print}' file        ;用cc替换aa
awk '{sub(/aa/,"cc",$1); print}' file    ;第一个域内用cc替换aa

把上面sub换成gsub就表示在满足条件的域里面替换所有的字符。

比如如下文件内容:

aa我们    aa我们
aaaa一起    aaaa一起
回家    aa回家

使用上述的awk的sub的2个参数的用法awk '{sub(/aa/,"cc");print}' file,可以得到如下结果

cc我们    aa我们       #只改变坐起第一个aa
ccaa一起    aaaa一起
回家    cc回家      #第一个字段中没有aa,就继续寻找下一个字段,直到找到第一个aa并替换

使用sub的第二种3参数用法awk '{sub(/aa/,"cc",$1); print}' file,结果如下

cc我们    aa我们    
ccaa一起    aaaa一起
回家   aa回家       #第一个字段中没有aa直接结束本行的替换

如果使用gsub,两种不同参数的方法得到的结果分别如下

#不加$1
cc我们    cc我们
cccc一起    cccc一起        #全部替换
回家   cc回家

#添加$1
cc我们   aa我们
cccc一起   aaaa一起
回家    aa回家                #第一个域内全部替换,其他域不管


awk的sub函数用法:
sub函数匹配指定域/记录中最大、最靠左边的子字符串的正则表达式,并用替换字符串替换这些字符串。
如果没有指定目标字符串就默认使用整个记录。替换只发生在第一次匹配的时候。格式如下:

sub (regular expression, substitution string):
sub (regular expression, substitution string, target string)

实例:

$ awk '{ sub(/test/, "mytest"); print }' testfile
$ awk '{ sub(/test/, "mytest", $1); print }' testfile

      第一个例子在整个记录中匹配,替换只发生在第一次匹配发生的时候。
      第二个例子在整个记录的第一个域中进行匹配,替换只发生在第一次匹配发生的时候。
如要在整个文件中进行匹配需要用到gsub
gsub函数作用如sub,但它在整个文档中进行匹配。格式如下:

gsub (regular expression, substitution string)
gsub (regular expression, substitution string, target string)

实例:

$ awk '{ gsub(/test/, "mytest"); print }' testfile
$ awk '{ gsub(/test/, "mytest", $1); print }' testfile

      第一个例子在整个文档中匹配test,匹配的都被替换成mytest。
      第二个例子在整个文档的第一个域中匹配,所有匹配的都被替换成mytest。
另外, 只有当记录中的域有改变的时候 ,指定0FS变量才有用, 如果记录中的域无变化, 指定OFS产生不了实际效果。


awk -F'|' -v OFS='|' '{ gsub(/[0-9]/, "", $3); print $0; }' data.txt   


将把第三个域中所有数字都去掉。


另外,对于数字的匹配,可以使用十六进制。


awk -F'|' -v OFS='|' '{ gsub(/[/x30-/x39]/, "", $3); print $0; }' data.txt 

<think>嗯,用户之前问过如何查看/dev/mtd*的大小,现在他问的是关于如何用awk提取mtd0行的00040000这个值。我需要先理解用户的问题。 首先,用户提供的例子是“mtd0: 00040000 00010000 "BL2"”,想要用awk提取第一个数值00040000。可能用户需要处理/proc/mtd文件中的内容,自动提取分区大小,用于脚本或其他用途。 用户之前得到过用cat /proc/mtd的示例,里面提到第二列是大小,第三列是擦除块大小。现在他可能想用awk来自动化提取这个值,比如在脚本中使用。这可能涉及到文本处理,使用awk来分割字段。 我需要检查原来的回答中是否有提到使用awk的方法。在第五点自动化脚本里,确实有用到awk来提取sizename。用户可能看到了这个部分,但想单独提取某个字段,所以需要具体的awk命令。 用户的问题是如何使用awk提取00040000,也就是第二列。在示例中,行格式是“mtd0: 00040000 00010000 "BL2"”,字段之间用空格分隔。但需要注意冒号的存在,比如第一个字段是mtd0:,后面可能有冒号分隔。 使用awk的话,可能需要处理字段分隔符。默认情况下,awk以空格或制表符分隔字段,但第一个字段是“mtd0:”,包含冒号。所以需要处理这个情况,可能用-F参数设置分隔符。 可能的命令是:awk &#39;{print $2}&#39;,但需要确认分割后的字段是否正确。例如,对于行“mtd0: 00040000 00010000 "BL2"”,分割后的字段可能是: $1: mtd0: $2: 00040000 $3: 00010000 $4: "BL2" 所以第二个字段就是需要的值。不过,冒号可能被当作分隔符的一部分,导致分割后的字段不同。如果默认用空格分隔,那么可能第一个字段是mtd0:,第二个是00040000,第三个是00010000,第四个是"BL2"。这时候需要处理第一个字段中的冒号。 或者,可以使用-F参数来指定字段分隔符为冒号加空格,或者用正则表达式分割多个空格。或者用substr或split函数处理第一个字段。 但可能更简单的方法是用默认的空格分隔,然后处理第一个字段中的冒号。例如,使用sub函数去掉冒号: awk &#39;{gsub(/:/,"",$1); print $2}&#39; 或者直接使用$2,因为分隔符是空格,而第一个字段是mtd0:,所以第二个字段就是00040000。 测试一下,假设输入行是“mtd0: 00040000 00010000 "BL2"”,默认分割后的字段: $1: mtd0: $2: 00040000 $3: 00010000 $4: "BL2" 所以,直接使用$2即可得到00040000。但用户可能需要处理的是/proc/mtd中的行,例如,在之前的示例中,输出行的格式是“mtd0: 00040000 00010000 "bootloader"”,所以同样的逻辑适用。 因此,正确的awk命令应该是: awk &#39;/^mtd0:/ {print $2}&#39; 或者更通用的,提取任意mtd分区的第二个字段: cat /proc/mtd | awk &#39;{print $2}&#39; 但需要过滤掉可能存在的其他行,比如标题行,如果有的话。但/proc/mtd通常没有标题行,每行都是类似的结构。 所以,针对用户的具体例子,提取mtd0行的第二个字段,可以使用: cat /proc/mtd | grep &#39;mtd0:&#39; | awk &#39;{print $2}&#39; 或者直接使用awkawk &#39;/^mtd0:/ {print $2}&#39; /proc/mtd 这样就能得到00040000。 用户可能需要这个值用于脚本中的变量赋值,比如size=$(...),所以需要确保命令正确无误。 另外,用户可能还希望处理十六进制到十进制的转换,比如将00040000转换为十进制,可以用awk的内置函数或者shell的计算方法。例如: awk &#39;/^mtd0:/ {print strtonum("0x"$2)}&#39; 或者: echo $((0x00040000)) 但用户的问题只是提取数值,所以重点在如何用awk正确获取第二个字段。 总结:使用awk &#39;{print $2}&#39;来处理/proc/mtd中对应的行,即可提取所需的值。需要先用grep匹配对应的mtd行,或者在awk中处理模式匹配。</think>在Linux系统中,使用`awk`提取`mtd0: 00040000 00010000 "BL2"`中的`00040000`值,可以通过以下方法实现: --- ### **方法一:基础提取(直接定位字段)** ```bash echo &#39;mtd0: 00040000 00010000 "BL2"&#39; | awk &#39;{print $2}&#39; ``` **输出结果**: ``` 00040000 ``` **原理**: 1. 默认以空格为分隔符 2. `$1`对应`mtd0:` 3. `$2`对应第一个数值`00040000` --- ### **方法二:精准匹配(过滤特定mtd分区)** ```bash cat /proc/mtd | awk &#39;/^mtd0:/ {print $2}&#39; ``` **操作说明**: 1. `/^mtd0:/` 匹配以`mtd0:`开头的行 2. `{print $2}` 输出第二个字段 --- ### **方法三:批量提取(适用于所有mtd分区)** ```bash cat /proc/mtd | awk -F &#39;[ :]+&#39; &#39;{print $1, $3}&#39; ``` **输出示例**: ``` mtd0 00040000 mtd1 00280000 ... ``` **参数解析**: - `-F &#39;[ :]+&#39;`:设置分隔符为**连续的空格或冒号** - `$1`:分区名称(如`mtd0`) - `$3`:分区大小(如`00040000`) --- ### **方法四:十六进制转十进制(直接计算)** ```bash echo &#39;mtd0: 00040000 00010000 "BL2"&#39; | awk &#39;{print strtonum("0x"$2)}&#39; ``` **输出结果**: ``` 262144 ``` **说明**: - `strtonum("0x"$2)` 将十六进制值转换为十进制 - 等价于:$$ 0x00040000 = 262144 \text{ bytes} = 256 \text{ KB} $$ --- ### **方法五:脚本集成(带单位换算)** ```bash cat /proc/mtd | awk &#39; { size_hex = $2; size_dec = strtonum("0x" size_hex); printf "%s → %d bytes (%d KB)\n", $1, size_dec, size_dec/1024 }&#39; ``` **输出示例**: ``` mtd0: → 262144 bytes (256 KB) mtd1: → 2621440 bytes (2560 KB) ... ``` --- ### **关键点总结** | 操作目标 | awk实现要点 | |------------------------|-----------------------------------------| | 提取原始十六进制值 | `awk &#39;{print $2}&#39;` | | 精准匹配指定分区 | `awk &#39;/^mtd0:/ {print $2}&#39;` | | 去除冒号干扰 | `-F &#39;[ :]+&#39;` 多分隔符支持 | | 十六进制转十进制 | `strtonum("0x"$2)` | | 脚本友好输出 | `printf` 格式化输出 | --- ### **常见问题处理** 1. **字段错位问题**: - 若输出包含多余空格,使用 `-F &#39;[ :]+&#39;` 正则表达式分隔符 - 示例修正: ```bash awk -F &#39;[ :]+&#39; &#39;{print $2}&#39; # 提取第一个数值字段 ``` 2. **自动化脚本示例**: ```bash #!/bin/bash for mtd in /dev/mtd*; do devnum=${mtd#/dev/mtd} size_hex=$(awk -F &#39;[ :]+&#39; &#39;/^mtd&#39;$devnum&#39;:/ {print $3}&#39; /proc/mtd) size_dec=$((0x$size_hex)) echo "$mtd size: $size_dec bytes" done ``` 通过上述方法,可以灵活提取并处理MTD分区信息,适用于嵌入式开发、固件分析等场景。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值