以空格作为分隔符时 cut和awk处理的差异

本文详细对比了Linux环境下cut命令和awk命令在处理多空格间隔文本时的功能与局限性,并通过实例展示了awk命令在排序和输出字段方面的优势。此外,文章还探讨了cut命令的使用场景和不足之处。


http://blog.163.com/hot4321@126/blog/static/16538535820105613258809/

[rocrocket@rocrocket programming]$ cat tab_space.txt |cut -d ' ' -f 1
this
this注意,两个单引号之间可确实要有一个空格哦,不能偷懒。
而且,你只能在-d后面设置一个空格,可不许设置多个空格,因为cut只允许间隔符是一个字符。

ls -lc | cut -d ' '   -s -f 8-

10 cut有哪些缺陷和不足?

猜出来了吧?对,就是在处理多空格时。
如果文件里面的某些域是由若干个空格来间隔的,那么用cut就有点麻烦了,因为cut只擅长处理“以一个字符间隔”的文本内容

/* 参考:

http://linuxop.blog.51cto.com/13377/249094
结论:
awk 以空格为分割域时,是以单个或多个连续的空格为分隔符的;
cut则是以单个空格作为分隔符。

*/


例子:
[wyh@ qt-everywhere-opensource-src-4.7.4 12:22:25]$ls -lc | awk '{print $6,$7,$8,$9}' | sort > /tmp/ls_lc_sorted.txt
[wyh@ qt-everywhere-opensource-src-4.7.4 12:22:46]$ls --time=c -lrth | awk '{print $6,$7,$8,$9}' > /tmp/ls_time-c_lrth.txt


GOOGLE:  linux awk printf field till line end  $NF;

awk中只能使用for循环!:

You could use a for-loop to loop through printing fields $2 through $NF (built-in variable that represents the number of fields on the line).

Edit: Since "print" appends a newline, you'll want to buffer the results: awk '{out=""; for(i=2;i<=NF;i++){out=$out" "$i}; print $out}'

 Alternatively, use printf:   awk 'for(i=2;i<=NF;i++){printf "%s ", $i}; printf "\n"}'

 

 

 

<think> 我们有一个字符串 a="pptp/wan1/192.168.0.1/24-192.168.1.1/24" 要提取的字符串有两个: 1. "wan1" 2. "192.168.0.1/24-192.168.1.1/24" 下面分别用cutawk命令来实现: 1. 提取"wan1" 使用cut命令: cut命令使用分隔符'/',并选取第二个字段(因为第一个字段是"pptp",第二个是"wan1") 命令:echo $a | cut -d'/' -f2 使用awk命令: awk同样使用分隔符'/',并打印第二个字段 命令:echo $a | awk -F'/' '{print $2}' 2. 提取"192.168.0.1/24-192.168.1.1/24" 注意:这个字符串从第三个字段开始,但是后面还有多个字段,而且这些字段中也有分隔符'/',所以我们不能简单地取一个字段。 使用cut命令: 由于cut不支持取多个字段(除非连续位置),但这里我们需要从第三个字段到最后一个字段。我们可以使用: cut命令可以指定连续字段,例如-f3-,表示从第三个字段到最后一个字段。 命令:echo $a | cut -d'/' -f3- 使用awk命令: 使用awk,我们可以设置输出分隔符OFS(默认为空格),但我们希望保留原有的分隔符,所以我们可以重建从第三个字段开始的字符串。 方法一:使用循环拼接字段 echo $a | awk -F'/' '{out=$3; for(i=4;i<=NF;i++){out=out"/"$i}; print out}' 方法二:使用substrindex函数多次处理(复杂) 这里推荐方法一。 但是注意,原字符串中的第二部分是"192.168.0.1/24-192.168.1.1/24",我们使用上述方法提取后应该就是这个字符串。 验证: 字符串a被'/'分割后,字段如下: 1. pptp 2. wan1 3. 192.168.0.1 4. 24-192.168.1.1 5. 24 而我们想要的是:字段3到字段5,并用'/'连接,即:192.168.0.1/24-192.168.1.1/24 但是注意,分割后第四个字段是"24-192.168.1.1",第五个字段是24。所以用上面的cut命令 -f3- 得到的是: 192.168.0.1/24-192.168.1.1/24 这正是我们想要的。 因此,两种命令的用法总结如下: 提取"wan1": cut: echo $a | cut -d'/' -f2 awk: echo $a | awk -F'/' '{print $2}' 提取"192.168.0.1/24-192.168.1.1/24": cut: echo $a | cut -d'/' -f3- awk: echo $a | awk -F'/' '{out=$3; for(i=4;i<=NF;i++){out=out"/"$i}; print out}' 下面我们进行实际测试(在shell中): a="pptp/wan1/192.168.0.1/24-192.168.1.1/24" 提取wan1: cut: 输出wan1 awk: 输出wan1 提取IP范围: cut: 输出192.168.0.1/24-192.168.1.1/24 awk: 输出192.168.0.1/24-192.168.1.1/24 注意:在awk命令中,我们用循环重建了字符串,从第三个字段开始,然后每个字段前面加上一个'/',这样就把原来的分割符加回去了。 另外,我们也可以使用其他方法,比如用sed替换掉前两个字段,但题目要求用cutawk。 所以,按照要求,我们给出cutawk的用法解释。 </think> ### 使用cutawk命令提取字符串的详细解释 #### 1. 提取"wan1"的方法 **cut命令解决方案:** ```bash echo "$a" | cut -d'/' -f2 ``` - **参数解析**: - `-d'/'`:设置分隔符为斜杠 `/` - `-f2`:选择第二个字段(字段索引从1开始) - **处理过程**: ```mermaid graph LR A[pptp/wan1/192.168...] --> B[分割成字段] B --> C1[字段1: pptp] B --> C2[字段2: wan1] B --> C3[字段3: 192.168.0.1] C2 --> D[输出wan1] ``` **awk命令解决方案:** ```bash echo "$a" | awk -F'/' '{print $2}' ``` - **参数解析**: - `-F'/'`:设置字段分隔符为 `/` - `{print $2}`:打印第二个字段 - **优势**: - 支持正则表达式分隔(如 `-F'[/-]'` 可同按`/``-`分割) - 可处理更复杂的字段关系(如条件判断) #### 2. 提取"192.168.0.1/24-192.168.1.1/24"的方法 **cut命令解决方案:** ```bash echo "$a" | cut -d'/' -f3- ``` - **参数解析**: - `-f3-`:选择从第三个字段到结尾的所有内容 - **注意事项**: - 依赖固定的字段位置(前两个必须是协议/接口名) - 保留原始分隔符 `/`,适合简单连续字段提取 **awk命令解决方案:** ```bash echo "$a" | awk -F'/' '{out=$3; for(i=4;i<=NF;i++){out=out"/"$i}; print out}' ``` - **参数解析**: - `NF`:内置变量,表示字段总数 - `for(i=4;i<=NF;i++)`:遍历第4个到最后一个字段 - `out=out"/"$i`:用`/`重新拼接字段 - **处理逻辑**: $$ \text{输出} = \bigcup_{k=3}^{NF} \begin{cases} \text{字段}_k & \text{如果 } k=3 \\ \text{"/" + 字段}_k & \text{如果 } k>3 \end{cases} $$ - **优势**: - 动态适应字段数量变化 - 可处理不固定长度的路径(如云配置中的网络路径)[^3] #### 3. 命令对比总结 | 特性 | cut命令 | awk命令 | |---------------------|----------------------------------|----------------------------------| | **字段提取** | 简单字段选择 | 支持字段重组计算 | | **分隔符灵活性** | 仅支持单字符分隔符 | 支持正则表达式分隔符 | | **复杂处理能力** | 有限 | 支持循环、条件判断等编程结构 | | **适用场景** | 固定格式的简单提取 | 变长字段或需要重组的复杂提取 | | **性能** | 更高(单一工具) | 稍低(完整编程语言) | | **典型应用** | 日志解析、配置文件读取 | 网络配置处理[^3]、数据转换 | #### 4. 实际应用示例 在Kubernetes网络配置中处理类似格式: ```bash # 示例:提取OpenStack子网配置中的IP范围 config="neutron/tenantA/10.10.0.0/24-10.10.1.0/24" subnet=$(echo "$config" | awk -F'/' '{out=$3; for(i=4;i<=NF;i++){out=out"/"$i}; print out}') echo "配置的子网范围: $subnet" ``` 这会输出:`10.10.0.0/24-10.10.1.0/24`,可直接用于iptables规则生成[^1]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值