awk定义字段模式

时间:2013-06-17 11:45:04

标签: bash awk

我正在寻找一种方法,使用awk将以下文本拆分为适当的列。

我有

[2013-06-17 13:30] [PACMAN] Running 'pacman -S cups'
[2013-06-17 13:30] [PACMAN] reinstalled cups (1.6.2-2)

所以,关于:

[2013-06-17 13:30] [PACMAN] Running 'pacman -S cups'

我想:

$1 to be [2013-06-17 13:30]
$2 to be [PACMAN] 
$3 to be Running
$4 to be 'pacman -S cups'

有:

[2013-06-17 13:30] [PACMAN] reinstalled cups (1.6.2-2)

我想:

$1 to be [2013-06-17 13:30]
$2 to be [PACMAN]
$3 to be reinstalled
$4 to be cups (1.6.2-2)

我做了很多谷歌搜索,找不到任何东西,我对awk来说还是新手

3 个答案:

答案 0 :(得分:3)

(以下内容似乎特定于GNU awk; BSD awk不支持将子组捕获到数组中。)

在这种情况下,您可能希望将整个字符串与特定正则表达式匹配,而不是依赖于awk的字段拆分。

$ echo "[2013-06-17 13:30] [PACMAN] Running 'pacman -S cups'" | awk '
    {
       match($0, "^(\\\[.*\\\]) (\\\[.*\\\]) ([a-zA-Z]*) (.*)$", a);
       $1=a[1];
       $2=a[2];
       $3=a[3];
       $4=a[4];
       print $2
    }'
[PACMAN]

调用match后,数组a将填充$0中与正则表达式匹配的文本。第0个元素是整个匹配字符串,其余元素设置为正则表达式中对应的带括号的组。

可能有更好的方法来编写正则表达式;我收到关于\[被视为普通[的警告,但总的来说它似乎有效。

答案 1 :(得分:1)

对于不优雅的方法,请参见下面的第四个单行。有用!!但你可能不想接受我的回答。该命令很嘈杂,您可能需要将注释添加为“文档”以使其可维护。出于这个原因,我将其作为.awk文件包含在下面: - )

尽管如此,即使文件的格式相当简单,我认为最好的方法是使用正则表达式作为@chepner注释。如果只是因为它自己记录。

~/$ cat test.txt 
[2013-06-17 13:30] [PACMAN] Running 'pacman -S cups'
[2013-06-17 13:30] [PACMAN] reinstalled cups (1.6.2-2)

1)第一栏:

 ~/$ awk -F '[\]]' '{print $1"]"}' test.txt 
 [2013-06-17 13:30]
 [2013-06-17 13:30]

2)第一栏和第二栏:

~/$ awk -F '[\]]' '{print $1"]" $2"]" }' test.txt 
[2013-06-17 13:30] [PACMAN]
[2013-06-17 13:30] [PACMAN]

3)所有三个:

~/$ awk -F '[\]]' '{print $1"]" $2"]"  $3}' test.txt
[2013-06-17 13:30] [PACMAN] Running 'pacman -S cups'
[2013-06-17 13:30] [PACMAN] reinstalled cups (1.6.2-2)

4)与上述相同,但将第三个字段拆分为数组a,以便分别打印Runningreinstalled。从第一个元素的a取得的偏移量(substr)开始打印数组oslength)的子字符串。

~/$ awk -F ']' '{split($3,a," "); os=(length(a[1])+2) ; print $1"]" $2"] " a[1]" " substr($3,os) }' test.txt
[2013-06-17 13:30] [PACMAN] Running 'pacman -S cups'
[2013-06-17 13:30] [PACMAN] reinstalled cups (1.6.2-2)

这是BSD awk所以它应该适用于OSX。

# split.awk ... run with: awk -f split.awk  data.txt

BEGIN{
FS="]"   # Make the field separator be "]"
}
{
  # Split the third field into array "a"
  split($3,a," ") 
  os=(length(a[1])+2) 
   # Print the first two fields and a substring of array "a" (substr)            
   # starting at offset ("os") taken from the length of the first element 
   # right adjusted for two whitespaces.
  print $1"]" $2"] " a[1]" " substr($3,os) 
}

HTH。

答案 2 :(得分:0)

在我的脑海中,对于你想要的第3和第5个领域(以及缺少的第4个)你想要的东西有点混乱。

第一种方式: 我的试验是基于引入一个新的分隔符,我们希望将这些分隔符分开......

命令:

~/so_test> cat ztmp_bk | sed -n 's/]/]^/gp'| awk -F"^" '{print $1 "==" $2 "==" $3 }'

输出:(由“==”标识的字段)

[2013-06-17 13:30]== [PACMAN]== Running 'pacman -S cups'
[2013-06-17 13:30]== [PACMAN]== reinstalled cups (1.6.2-2)
第二种方式:

替代方法是将文件切割成部分并再次为第3个文件执行,直到我们获得所需的单个coloumn然后我们可以使用使用用户定义的分隔符的粘贴合并它们...

如下所示:(非常粗糙,但你明白了!)

Kaizen ~/so_test/test $ cat ztmp  | sed -n 's/]/]^/gp'| awk -F"^" '{print $1 "^" $2}' > ztmp1 ;
Kaizen ~/so_test/test $  cat ztmp  | awk -F" " '{print   $4 "^" $5 $6 $7}' > ztmp2 ;
Kaizen ~/so_test/test $  paste -d^ ztmp1 ztmp2 > ztmpF ;

输出:这会给你一个^分隔的新文件,因此你以前的awk命令现在可以在这个文件上工作

Kaizen ~/so_test/test $ cat ztmpF
[2013-06-17 13:30]^ [PACMAN]^Running^'pacman-Scups'
[2013-06-17 13:30]^ [PACMAN]^reinstalled^cups(1.6.2-2)

Kaizen ~/so_test/test $ cat ztmpF | awk -F"^" '{print "first field:" $1 "\n" "second field:" $2 "\n" "third     field:" $3 "\n" "forth field:" $4 "\n" }'
first field:[2013-06-17 13:30]
second field: [PACMAN]
third field:Running
forth field:'pacman-Scups'

first field:[2013-06-17 13:30]
second field: [PACMAN]
third field:reinstalled
forth field:cups(1.6.2-2)

这有帮助吗?