回到:


详细分析awk字段分割

awk读取每一条记录之后,会将其赋值给$0,同时还会对这条记录按照预定义变量FS划分字段,将划分好的各个字段分别赋值给$1 $2 $3 $4...$N,同时将划分的字段数量赋值给预定义变量NF

引用字段的方式

$N引用字段:

  • N=0:即$0,引用记录本身
  • 0<N<=NF:引用对应字段
  • N>NF:表示引用不存在的字段,返回空字符串
  • N<0:报错

可使用变量或计算的方式指定要获取的字段序号。

awk '{n = 5;print $n}' a.txt
awk '{print $(2+2)}' a.txt   # 括号必不可少,用于改变优先级
awk '{print $(NF-3)}' a.txt

分割字段的方式

读取record之后,将使用预定义变量FS、FIELDWIDTHS或FPAT中的一种来分割字段。分割完成之后,再进入main代码段(所以,在main中设置FS对本次已经读取的record是没有影响的,但会影响下次读取)。

划分字段方式(一):FS或-F

FS或者-F:字段分隔符

  • FS为单个字符时,该字符即为字段分隔符
  • FS为多个字符时,则采用正则表达式模式作为字段分隔符
  • 特殊的,也是FS默认的情况,FS为单个空格时,将以连续的空白(空格、制表符、换行符)作为字段分隔符
  • 特殊的,FS为空字符串""时,将对每个字符都进行分隔,即每个字符都作为一个字段
  • 设置预定义变量IGNORECASE为非零值,正则匹配时表示忽略大小写(只影响正则,所以FS为单字时无影响)
  • 如果record中无法找到FS指定的分隔符(例如将FS设置为"\n"),则整个记录作为一个字段,即$1$0相等
# 字段分隔符指定为单个字符
awk -F":" '{print $1}' /etc/passwd
awk 'BEGIN{FS=":"}{print $1}' /etc/passwd

# 字段分隔符指定为正则表达式
awk 'BEGIN{FS=" +|@"}{print $1,$2,$3,$4,$5,$6}' a.txt

划分字段方式(二):FIELDWIDTHS

指定预定义变量FIELDWIDTHS按字符宽度分割字段,这是gawk提供的高级功能。在处理某字段缺失时非常好用。

用法:

示例1:

# 没取完的字符串DDD被丢弃,且NF=3
$ awk 'BEGIN{FIELDWIDTHS="2 3 2"}{print $1,$2,$3,$4}' <<<"AABBBCCDDDD"
AA BBB CC 

# 字符串不够长度时无视
$ awk 'BEGIN{FIELDWIDTHS="2 3 2 100"}{print $1,$2,$3,$4"-"}' <<<"AABBBCCDDDD"
AA BBB CC DDDD-

# *号取剩余所有,NF=3
$ awk 'BEGIN{FIELDWIDTHS="2 3 *"}{print $1,$2,$3}' <<<"AABBBCCDDDD"
AA BBB CCDDDD

# 字段数多了,则取完字符串即可,NF=2
$ awk 'BEGIN{FIELDWIDTHS="2 30 *"}{print $1,$2,NF}' <<<"AABBBCCDDDD"
AA BBBCCDDDD 2

示例2:处理某些字段缺失的数据。

如果按照常规的FS进行字段分割,则对于缺失字段的行和没有缺失字段的行很难统一处理,但使用FIELDWIDTHS则非常方便。

假设a.txt文本内容如下:

ID  name    gender  age  email          phone
1   Bob     male    28   abc@qq.com     18023394012
2   Alice   female  24   def@gmail.com  18084925203
3   Tony    male    21   aaa@163.com    17048792503
4   Kevin   male    21   bbb@189.com    17023929033
5   Alex    male    18                  18185904230
6   Andy    female  22   ddd@139.com    18923902352
7   Jerry   female  25   exdsa@189.com  18785234906
8   Peter   male    20   bax@qq.com     17729348758
9   Steven  female  23   bc@sohu.com    15947893212
10  Bruce   female  27   bcbd@139.com   13942943905

因为email字段有的是空字段,所以直接用FS划分字段不便处理。可使用FIELDWIDTHS。

# 字段1:4字符
# 字段2:8字符
# 字段3:8字符
# 字段4:2字符
# 字段5:先跳过3字符,再读13字符,该字段13字符
# 字段6:先跳过2字符,再读11字符,该字段11字符
awk '
BEGIN{FIELDWIDTHS="4 8 8 2 3:13 2:11"}
NR>1{
    print "<"$1">","<"$2">","<"$3">","<"$4">","<"$5">","<"$6">"
}' a.txt

# 如果email为空,则输出它
awk '
BEGIN{FIELDWIDTHS="4 8 8 2 3:13 2:11"}
NR>1{
    if($5 ~ /^ +$/){print $0}
}' a.txt

划分字段方式(三):FPAT

FS是指定字段分隔符,来取得除分隔符外的部分作为字段。

FPAT是取得匹配的字符部分作为字段。它是gawk提供的一个高级功能。

FPAT根据指定的正则来全局匹配record,然后将所有匹配成功的部分组成$1、$2...,不会修改$0

  • awk 'BEGIN{FPAT="[0-9]+"}{print $3"-"}' a.txt
  • 之后再设置FS或FPAT,该变量将失效

FPAT常用于字段中包含了字段分隔符的场景。例如,CSV文件中的一行数据如下:

Robbins,Arnold,"1234 A Pretty Street, NE",MyTown,MyState,12345-6789,USA

其中逗号分隔每个字段,但双引号包围的是一个字段整体,即使其中有逗号。

这时使用FPAT来划分各字段比使用FS要方便的多。

echo 'Robbins,Arnold,"1234 A Pretty Street, NE",MyTown,MyState,12345-6789,USA' |\
awk '
    BEGIN{FPAT="[^,]*|(\"[^\"]*\")"}
    {
        for (i=1;i<NF;i++){
            print "<"$i">"
        }
    }
'

最后,patsplit()函数和FPAT的功能一样。

检查字段划分的方式

有FS、FIELDWIDTHS、FPAT三种获取字段的方式,可使用PROCINFO数组来确定本次使用何种方式获得字段。

PROCINFO是一个数组,记录了awk进程工作时的状态信息。

如果:

  • PROCINFO["FS"]=="FS",表示使用FS分割获取字段
  • PROCINFO["FPAT"]=="FPAT",表示使用FPAT匹配获取字段
  • PROCINFO["FIELDWIDTHS"]=="FIELDWIDTHS",表示使用FIELDWIDTHS分割获取字段

例如:

if(PROCINFO["FS"]=="FS"){
    ...FS spliting...
} else if(PROCINFO["FPAT"]=="FPAT"){
    ...FPAT spliting...
} else if(PROCINFO["FIELDWIDTHS"]=="FIELDWIDTHS"){
    ...FIELDWIDTHS spliting...
}

精通awk系列(8):awk划分字段的3种方式的更多相关文章

  1. 【Xamarin 挖墙脚系列:IOS 开发界面的3种方式】

    原文:[Xamarin 挖墙脚系列:IOS 开发界面的3种方式] xcode6进行三种基本的界面布局的方法,分别是手写UI,xib和storyboard.手写UI是最早进行UI界面布局的方法,优点是灵 ...

  2. 精通awk系列(9):修改字段或NF引起的$0重新计算

    回到: Linux系列文章 Shell系列文章 Awk系列文章 修改字段或NF值的联动效应 注意下面的分割和计算两词:分割表示使用FS(field Separator),计算表示使用预定义变量OFS( ...

  3. GSON使用笔记(1) -- 序列化时排除字段的几种方式

    http://blog.csdn.net/zxhoo/article/details/21471005 GSON是Google发布的JSON序列化/反序列化工具,非常容易使用.本文简要讨论在使用GSO ...

  4. 我给女朋友讲编程CSS系列(1) –添加CSS样式的3种方式及样式表的优先权

    如果说,原生态就是美,那么,我们就没有必要穿衣打扮. 网页是什么? 说白了,网页就是一堆[html标签]有序的搭配,让[CSS属性值]整整容,请[Javascript语言]处理一下事件. 一个人的整容 ...

  5. Spark Scala语言学习系列之完成HelloWorld程序(三种方式)

    三种方式完成HelloWorld程序 分别采用在REPL,命令行(scala脚本)和Eclipse下运行hello world. 一.Scala REPL. windows下安装好scala后,直接C ...

  6. Spring系列4:依赖注入的2种方式

    本文内容 基于构造器的依赖注入 基于setter的依赖注入 基于构造器的依赖注入 案例 定义2个简单的bean类,BeanOne 和 BeanTwo,前者依赖后者. package com.crab. ...

  7. Docker系列教程04-Docker构建镜像的三种方式

    简介 创建镜像的方法主要有三种:基于已有镜像的容器创建.基于本地模板导入.基于Dockerfile创建. 今天就逐一讲述为大家讲述,如何构建属于自己的docker镜像. 1.基于容器构建镜像 基于已有 ...

  8. 精通awk系列文章

    精通awk系列文章 我录制了两个awk相关的视频教程: Awk经典实战案例精讲 精通awk精品课程:awk从入门到精通 1.安装新版本的gawk 2.本教程测试所用示例文件 3.铺垫知识:读取文件的几 ...

  9. 精通awk系列(10):awk筛选行和处理字段的示例

    回到: Linux系列文章 Shell系列文章 Awk系列文章 awk数据筛选示例 筛选行 # 1.根据行号筛选 awk 'NR==2' a.txt # 筛选出第二行 awk 'NR>=2' a ...

随机推荐

  1. C# Halcon联合编程问题(二)

    避免重复编辑同一篇随笔,有问题就开一个新的,哪怕会很短. 还是之前那个问题,halcon中的HObject转换为Bitmap的问题,在全网找相关的办法,三通道图像的HObject转换为C#中的Bitm ...

  2. python编程系列---最详细的讲解进程与线程的关系

    进程与线程 先引入三个比如: cpu---公司 进程---办公室   线程---程序员(我们)   全局变量,内存等资源---公司提供的电脑,桌子等 进程:  操作系统分配程序执行资源的单位 线程:进 ...

  3. HTML5+WebGL 的加油站 3D 可视化监控

    前言 随着数字化,工业互联网,物联网的发展,我国加油站正向有人值守,无人操作,远程控制的方向发展,传统的人工巡查方式逐渐转变为以自动化控制为主的在线监控方式,即采用数据采集与监控系统 SCADA.SC ...

  4. mysql 主从关系ERROR 1872 (HY000): Slave failed to initialize relay log info structure from the repository

    连接 amoeba-mysql出现Could not create a validated object, cause: ValidateObject failed mysql> start s ...

  5. 【Java必修课】各种集合类的合并(数组、List、Set、Map)

    1 介绍 集合类可谓是学习必知.编程必用.面试必会的,而且集合的操作十分重要:本文主要讲解如何合并集合类,如合并两个数组,合并两个List等.通过例子讲解几种不同的方法,有JDK原生的方法,还有使用第 ...

  6. 面试官:"准备用HashMap存1w条数据,构造时传10000还会触发扩容吗?"

    // 预计存入 1w 条数据,初始化赋值 10000,避免 resize. HashMap<String,String> map = new HashMap<>(10000) ...

  7. Sublime Text 3 安装 Package Control 结果返回 275309,找不到 Install Package

    打开 Preferences->Settings , 查看 ignored-packages 数组中是否有 Package Control,如果有,删除即可.

  8. vue 组件样式如何不影响全局

    可以在 "style" 标签中添加 "scoped" 属性. <style scoped> .red { color: #f00; } </s ...

  9. Hadoop 在 windows 7 64位的配置(二)|非cygwin

    第一次使用需要 hdfs namenode -format 一键启动和关闭hadoop 新建文本文档 然后改名 start-hadoop.cmd 里面的内容 @echo off cd /d %HADO ...

  10. .net layui 批量导出

    .net开发,前台使用layui框架,后台使用WCF 废话不多,直接上代码 1>文件引用: admin.css layui.css layui.js jquery.min.js layerToo ...