awk 不一樣的分隔符 - 空格分隔符

今天用 awk 格式化字符串的時候,發現了一個奇怪現象,查看了 awk 手冊後,特以此文記錄。

示例文本內容

後文所有 awk 語名中出現的 file.txt 內容均如下:

# cat -A file.txt
     1^Iroot:x:0:0:root:/root:/bin/bash$
     2^Ibin:x:1:1:bin:/bin:/sbin/nologin$
     3^Idaemon:x:2:2:daemon:/sbin:/sbin/nologin$

現象描述

通過 awk -F 的 "[]" 指定多個分隔符(包含空格)的時候,連續的空格被分隔成了多個字段。

awk 默認以空白字符(包含空格、TAB 字符、換行符)做爲分隔符,爲了更直觀對比,此處示例直接通過 -F 參數指定。簡單示例對比下:

我們先指定空格做爲分隔符來獲取第二個字段

# awk -F " " '{print NF, $2}' file.txt
2 root:x:0:0:root:/root:/bin/bash
2 bin:x:1:1:bin:/bin:/sbin/nologin
2 daemon:x:2:2:daemon:/sbin:/sbin/nologin

再通過 [] 指定空格分隔符來獲取

# awk -F "[ ]" '{print NF, $6}' file.txt
6 1 root:x:0:0:root:/root:/bin/bash
6 2 bin:x:1:1:bin:/bin:/sbin/nologin
6 3 daemon:x:2:2:daemon:/sbin:/sbin/nologin

是不是好奇怪,我們通過 -F " " 做爲分隔符的時候,每行只有 2 個字段,而通過 -F "[ ]" 做分隔符的時候,每行共有 6 個字段。$1-$5 獲取的值爲空,而 $6 確打印了全部內容。

查看 awk 手冊:
4.5.1 Whitespace Normally Separates Fields

awk interpreted this value in the usual way, each space character would separate fields, so two spaces in a row would make an empty field between them. The reason this does not happen is that a single space as the value of FS is a special case—it is taken to specify the default manner of delimiting fields.

If FS is any other single character, such as ",", then each occurrence of that character separates two fields. Two consecutive occurrences delimit an empty field. If the character occurs at the beginning or the end of the line, that too delimits an empty field. The space character is the only single character that does not follow these rules.

4.5.2 Using Regular Expressions to Separate Fields

There is an important difference between the two cases of ‘FS = " "’ (a single space) and ‘FS = "[ \t\n]+"’ (a regular expression matching one or more spaces, TABs, or newlines). For both values of FS, fields are separated by runs (multiple adjacent occurrences) of spaces, TABs, and/or newlines. However, when the value of FS is " ", awk first strips leading and trailing whitespace from the record and then decides where the fields are. 

awk 手冊

這兩段內容剛好解釋了這個奇怪的現象。大概意思就是:

  • 行中的連續空格不會分隔空字段。當 FS 的值爲 " " 時,awk 首先從記錄中去除行首和行尾的空白,然後再分割字段。
  • 如果 FS 是其他字符,比如”,“,連續兩次出現將分隔一個空字段。如果字符出現在行首或行尾,也會分隔空字段。空格字符做爲默認分隔符,是唯一不遵守這些規則的字符。
  • 如果通過 -F "[ ]" 指定,執表示通過單個空格分隔,此時,將失去其做爲默認分隔符的特性,與其它字符一樣,遵守同樣的分隔規則。

總結

結合上面內容,我們再來看幾個示例,對今天的內容做個總結。

示例:
awk 不一樣的分隔符 - 空格分隔符

總結:

  • 示例一,沒有指定分隔符,用的默認分隔符,此時行首的連續空白字符被自動去除。
  • 示例二,指定分隔符爲空格,等價於默認分隔符。
  • 示例三,指定分隔符爲一個或多個連續的“冒號或 tab 鍵“,此時行首多個連續空白字符被一起計入第一個字段。
  • 示例四,指定分隔符爲一個或多個連續的”空白字符或冒號或 tab 鍵“,此時行首多個連續的空白字符被分隔爲一個獨立的字段。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章