正则表达式
1.Linux grep 命令
Linux grep (global regular expression) 命令用于查找文件里符合条件的字符串或正则表达式。
grep 指令用于查找内容包含指定的范本样式的文件,如果发现某文件的内容符合所指定的范本样式,预设 grep 指令会把含有范本样式的那一列显示出来。若不指定任何文件名称,或是所给予的文件名为 -,则 grep 指令会从标准输入设备读取数据。
语法
bash
grep [options] pattern [files]
或
grep [-abcEFGhHilLnqrsvVwxy][-A<显示行数>][-B<显示列数>][-C<显示列数>][-d<进行动作>][-e<范本样式>][-f<范本文件>][--help][范本样式][文件或目录...]
常用参数
更多参数
以下是按照要求为每个案例分别创建所需文件或目录后再执行相应操作的详细脚本:
案例 1:在文件 file.txt 中查找字符串 "hello",并打印匹配的行
bash
# 创建 file.txt 文件并添加包含 "hello" 的内容
if [! -f file.txt ]; then
echo "This line has hello in it" > file.txt
fi
# 在 file.txt 中查找 "hello" 并打印匹配行
echo "案例 1:在文件 file.txt 中查找字符串 \"hello\",并打印匹配的行"
grep hello file.txt
echo ""
案例 2:在文件夹 dir 中递归查找所有文件中匹配正则表达式 "pattern" 的行,并打印匹配行所在的文件名和行号
bash
# 创建 dir 目录及包含 "pattern" 的文件
if [! -d dir ]; then
mkdir dir
touch dir/file_with_pattern.txt
echo "This line contains the pattern" > dir/file_with_pattern.txt
fi
# 在 dir 目录中递归查找 "pattern" 并打印匹配信息
echo "案例 2:在文件夹 dir 中递归查找所有文件中匹配正则表达式 \"pattern\" 的行,并打印匹配行所在的文件名和行号"
grep -r -n pattern dir/
echo ""
案例 3:在标准输入中查找字符串 "world",并只打印匹配的行数
bash
# 此案例无需创建文件,直接操作
echo "案例 3:在标准输入中查找字符串 \"world\",并只打印匹配的行数"
echo "hello world" | grep -c world
echo ""
案例 4:在当前目录中,查找后缀有 file 字样的文件中包含 test 字符串的文件,并打印出该字符串的行
bash
# 创建后缀有 file 字样且包含 test 的文件
if [! -f testfile1 ]; then
touch testfile1
echo "This a Linux testfile!" > testfile1
fi
if [! -f testfile_2 ]; then
touch testfile_2
echo "This is a linux testfile!" > testfile_2
echo "Linux test" >> testfile_2
fi
# 在相关文件中查找 "test" 并打印匹配行
echo "案例 4:在当前目录中,查找后缀有 file 字样的文件中包含 test 字符串的文件,并打印出该字符串的行"
grep test *file
echo ""
案例 5
bash
# 创建 /etc/acpi 目录及示例文件
sudo mkdir -p /etc/acpi
file_path="/etc/acpi/update_file.txt"
if [! -f $file_path ]; then
sudo touch $file_path
sudo echo "This line has update" > $file_path
fi
# 在 /etc/acpi 目录及其子目录中递归查找 "update" 并打印匹配行
echo "案例 5:以递归的方式查找指定目录 /etc/acpi 及其子目录下所有文件中包含字符串 \"update\" 的文件,并打印出该字符串所在行的内容"
grep -r update /etc/acpi
echo ""
案例 6
bash
# 创建相关文件
file1="testfile1"
file2="testfile2"
if [! -f $file1 ]; then
touch $file1
echo "No test here" > $file1
fi
if [! -f $file2 ]; then
touch $file2
echo "Just a simple line" > $file2
fi
# 在相关文件中反向查找不包含 "test" 的行并打印
echo "案例 6:反向查找,查找文件名中包含 test 的文件中不包含 test 的行"
grep -v test *test*
2.Linux awk 命令
awk 是一种处理文本文件的语言,是一个强大的文本分析工具。
awk 通过提供编程语言的功能,如变量、数学运算、字符串处理等,使得对文本文件的分析和操作变得非常灵活和高效。
之所以叫 awk 是因为其取了三位创始人 Alfred Aho,Peter Weinberger, 和 Brian Kernighan 的 Family Name 的首字符。
语法
bash
awk options 'pattern {action}' file
以下是一些常见的 awk 命令用法:
以下将从创建文件开始,对每个 awk
命令用法案例进行单独讲解:
1. 创建测试文件
首先,创建一个用于测试的文件 file
,并添加一些示例数据,以便后续演示 awk
的各种用法。
bash
#!/bin/bash
# 创建测试文件 file 并写入示例数据
echo "apple,3,5
banana,4,7
cherry,2,6
date,5,9" > file
2. 案例 1:打印整行
bash
echo "案例 1:打印整行"
awk '{print}' file
echo ""
解释:
awk
是一个强大的文本处理工具,用于处理文本文件中的数据。- 在这个命令中,
{print}
是awk
的操作部分。print
是一个内置函数,用于输出内容。 - 由于没有指定任何特定的列或条件,
awk
会默认对文件file
中的每一行进行操作,将整行内容原样输出。
3. 案例 2:打印特定列
bash
echo "案例 2:打印特定列"
awk '{print $1, $2}' file
echo ""
解释:
{print $1, $2}
是awk
的操作部分。$1
和$2
分别表示文件中每行按默认分隔符(空格或制表符)分割后的第一列和第二列。awk
会读取文件file
的每一行,将其按默认分隔符分割成列,然后输出第一列和第二列的内容。在我们创建的文件中,这将输出水果名称和对应的数量。
4. 案例 3:使用分隔符指定列
bash
echo "案例 3:使用分隔符指定列"
awk -F',' '{print $1, $2}' file
echo ""
解释:
-F','
是awk
的选项,用于指定字段分隔符。这里指定逗号,
为分隔符。{print $1, $2}
表示输出按指定分隔符(逗号)分割后的第一列和第二列。- 这样,
awk
会将文件file
中的每一行按逗号分割,然后输出第一列(水果名称)和第二列(数量)。
5. 案例 4:打印行数
bash
echo "案例 4:打印行数"
awk '{print NR, $0}' file
echo ""
解释:
NR
是awk
中的一个内置变量,代表当前处理的行号。$0
也是一个内置变量,代表当前处理的整行内容。{print NR, $0}
表示awk
在处理文件file
的每一行时,会输出该行的行号和整行内容。这样可以方便地查看每一行在文件中的位置以及具体内容。
6. 案例 5:打印行数满足条件的行
bash
echo "案例 5:打印行数满足条件的行"
awk '/banana/ {print NR, $0}' file
echo ""
解释:
/banana/
是一个正则表达式模式,用于匹配包含字符串banana
的行。{print NR, $0}
表示当某一行匹配到banana
这个模式时,awk
会输出该行的行号NR
和整行内容$0
。- 在文件
file
中,只有包含banana
的那一行会被匹配并输出其行号和内容。
7. 案例 6:计算列的总和
bash
echo "案例 6:计算列的总和"
awk '{sum += $2} END {print sum}' file
echo ""
解释:
{sum += $2}
:在处理文件file
的每一行时,awk
会将变量sum
初始化为 0(如果未定义),然后将每一行的第二列值累加到sum
中。这里的$2
表示按默认分隔符分割后的第二列。END
是awk
中的一个特殊块,当文件所有行处理完毕后,会执行END
块中的内容。{print sum}
在END
块中,用于输出累加后的总和。因此,这个命令会计算文件中第二列所有数值的总和。
8. 案例 7:打印最大值
bash
echo "案例 7:打印最大值"
awk 'max < $2 {max = $2} END {print max}' file
echo ""
解释:
max < $2 {max = $2}
:在处理文件file
的每一行时,awk
会将当前行的第二列值$2
与变量max
进行比较。如果$2
大于max
,则将max
更新为$2
。在处理第一行时,max
会被初始化为第一行的第二列值。END
块在文件所有行处理完毕后执行。{print max}
在END
块中,用于输出经过比较和更新后的max
值,即文件中第二列的最大值。
9. 案例 8:格式化输出
bash
echo "案例 8:格式化输出"
awk '{printf "%-10s %-10s\n", $1, $2}' file
解释:
printf
是awk
中的一个格式化输出函数,类似于 C 语言中的printf
。%-10s
表示左对齐,宽度为 10 个字符的字符串格式。这里第一个%-10s
用于格式化输出第一列$1
,第二个%-10s
用于格式化输出第二列$2
。\n
表示换行,确保每一行输出后换行。- 这个命令会按照指定的格式输出文件
file
中的每一行,使输出结果更加整齐美观。
清理测试文件
在所有案例演示完毕后,为了保持环境整洁,可以删除测试文件 file
。
bash
rm -f file
使用方法
- 将上述代码保存为一个脚本文件,例如
awk_demos.sh
。 - 为脚本文件添加执行权限:
chmod +x awk_demos.sh
。 - 运行脚本:
./awk_demos.sh
,观察每个案例的输出结果。
通过以上详细的讲解和示例,你可以更深入地理解和掌握 awk
的各种常见用法。
基本用法
以下将从创建文件开始,对每个 awk
用法案例进行详细分开讲解:
1. 创建测试文件
首先,创建一个名为 log.txt
的测试文件,并添加一些示例数据,用于后续的 awk
操作演示。
bash
#!/bin/bash
# 创建 log.txt 文件并添加内容
echo "2 this is a test
3 Do you like awk
This's a test
10 There are orange,apple,mongo" > log.txt
2. 用法一:awk '{[pattern] action}' {filenames}
这种形式下,awk
会按默认的分隔符(空格或制表符)对每行进行分割,然后根据指定的 action
进行操作。
实例 1:输出文本中的第 1、4 项
bash
echo "案例 1:用法一 - 实例 1:输出文本中的第 1、4 项"
awk '{print $1,$4}' log.txt
echo "---------------------------------------------"
代码解释:
awk '{print $1,$4}' log.txt
:这行命令中,awk
是命令本身,{print $1,$4}
是操作部分。print
是awk
的打印函数,$1
和$4
分别表示每行按默认分隔符(空格或制表符)分割后的第 1 列和第 4 列。log.txt
是要处理的文件名。
实例 2:格式化输出
bash
echo "案例 1:用法一 - 实例 2:格式化输出"
awk '{printf "%-8s %-10s\n",$1,$4}' log.txt
echo "---------------------------------------------"
代码解释:
awk '{printf "%-8s %-10s\n",$1,$4}' log.txt
:这里使用了printf
函数进行格式化输出。%-8s
表示左对齐,宽度为 8 个字符的字符串格式;%-10s
表示左对齐,宽度为 10 个字符的字符串格式。\n
表示换行。$1
和$4
同样是每行按默认分隔符分割后的第 1 列和第 4 列。
3. 用法二:awk -F
-F
相当于内置变量 FS
,用于指定分割字符。
实例 1:使用 ,
分割
bash
echo "案例 2:用法二 - 实例 1:使用, 分割"
awk -F, '{print $1,$2}' log.txt
echo "---------------------------------------------"
代码解释:
awk -F, '{print $1,$2}' log.txt
:-F,
表示将逗号,
设置为字段分隔符。{print $1,$2}
表示打印按逗号分割后的第 1 列和第 2 列。
实例 2:使用内建变量 FS
bash
echo "案例 2:用法二 - 实例 2:使用内建变量 FS"
awk 'BEGIN{FS=","} {print $1,$2}' log.txt
echo "---------------------------------------------"
代码解释:
awk 'BEGIN{FS=","} {print $1,$2}' log.txt
:BEGIN
块在处理文件内容之前执行,在这里将FS
(字段分隔符)设置为逗号,
。然后{print $1,$2}
打印按逗号分割后的第 1 列和第 2 列。
实例 3:使用多个分隔符
bash
echo "案例 2:用法二 - 实例 3:使用多个分隔符"
awk -F '[,]' '{print $1,$2,$5}' log.txt
echo "---------------------------------------------"
代码解释:
awk -F '[,]' '{print $1,$2,$5}' log.txt
:-F '[,]'
表示使用空格或逗号作为分隔符。{print $1,$2,$5}
表示打印按此分隔符分割后的第 1 列、第 2 列和第 5 列。
4. 用法三:awk -v
-v
用于设置变量,在 awk
脚本中可以使用这些自定义变量。
实例 1:设置单个变量
bash
echo "案例 3:用法三 - 实例 1:设置单个变量"
awk -va=1 '{print $1,$1+a}' log.txt
echo "---------------------------------------------"
代码解释:
awk -va=1 '{print $1,$1+a}' log.txt
:-va=1
表示设置一个名为a
的变量,其值为 1。{print $1,$1+a}
表示打印每行按默认分隔符分割后的第 1 列的值,以及第 1 列的值加上变量a
的结果。
实例 2:设置多个变量
bash
echo "案例 3:用法三 - 实例 2:设置多个变量"
awk -va=1 -vb=s '{print $1,$1+a,$1b}' log.txt
echo "---------------------------------------------"
代码解释:
awk -va=1 -vb=s '{print $1,$1+a,$1b}' log.txt
:-va=1
设置变量a
的值为 1,-vb=s
设置变量b
的值为s
。{print $1,$1+a,$1b}
表示打印每行按默认分隔符分割后的第 1 列的值、第 1 列的值加上变量a
的结果,以及第 1 列的值与变量b
连接后的结果。
5. 用法四:awk -f {awk脚本} {文件名}
通过 -f
选项可以指定一个 awk
脚本文件,然后对指定的文件名进行处理。
实例:使用外部 awk
脚本
bash
echo "案例 4:用法四 - 实例:使用外部 awk 脚本"
# 创建一个简单的 cal.awk 脚本
echo '{print $1, $2}' > cal.awk
awk -f cal.awk log.txt
echo "---------------------------------------------"
# 删除测试文件和临时脚本
rm -f log.txt cal.awk
代码解释:
echo '{print $1, $2}' > cal.awk
:创建一个名为cal.awk
的脚本文件,内容为打印每行的第 1 列和第 2 列。awk -f cal.awk log.txt
:使用-f
选项指定cal.awk
脚本,对log.txt
文件进行处理。
最后,rm -f log.txt cal.awk
用于删除创建的测试文件 log.txt
和临时脚本 cal.awk
。
使用方法:
- 将上述每个案例的代码分别保存为独立的脚本文件,例如
usage1.sh
、usage2.sh
等。 - 赋予每个脚本文件执行权限:
chmod +x [脚本文件名]
。 - 逐个运行脚本:
./[脚本文件名]
。
这样可以更清晰地看到每个 awk
用法案例的具体运行过程和结果。
运算符
1. 创建测试文件
首先创建一个用于测试的文件 log.txt
,并添加一些示例数据,这些数据将用于后续各种 awk
过滤操作的演示。
bash
#!/bin/bash
# 创建测试文件 log.txt 并写入示例数据
echo "2 this is a test
3 Do you like awk
This's a test
10 There are orange,apple,mongo" > log.txt
解释 :这里使用 echo
命令将几行文本内容输出到 log.txt
文件中。这些文本行将作为测试数据,方便我们展示不同的 awk
过滤命令的效果。
2. 案例 1:过滤第一列大于 2 的行
bash
echo "案例 1:过滤第一列大于 2 的行"
echo "命令:awk '$1>2' log.txt"
awk '$1>2' log.txt
echo ""
解释:
awk
是一个强大的文本处理工具,用于对文本文件进行逐行处理。- 在这个命令中,
$1
表示文件中每行按默认分隔符(空格或制表符)分割后的第一列。 $1>2
是一个条件表达式。awk
在读取log.txt
文件的每一行时,会对这一行进行分析,提取出第一列的值,然后将其与数字 2 进行比较。- 如果第一列的值大于 2,那么这一行就满足条件,
awk
会将这一行输出。因此,在我们的示例数据中,满足该条件的行 "3 Do you like awk"、"This's a test" 和 "10 There are orange,apple,mongo" 会被输出。
3. 案例 2:过滤第一列等于 2 的行
bash
echo "案例 2:过滤第一列等于 2 的行"
echo "命令:awk '$1==2 {print $1,$3}' log.txt"
awk '$1==2 {print $1,$3}' log.txt
echo ""
解释:
- 同样,
$1
代表每行的第一列。$1==2
是一个条件判断,用于检查每行的第一列的值是否等于 2。 {print $1,$3}
是当行满足$1==2
这个条件时执行的操作。它表示输出满足条件的行的第一列和第三列。- 当
awk
读取log.txt
文件的每一行时,会判断该行第一列是否等于 2。对于满足条件的行,awk
会输出该行的第一列和第三列。在我们的示例数据中,只有 "2 this is a test" 这一行满足条件,所以会输出 "2 is"。
4. 案例 3:过滤第一列大于 2 并且第二列等于 'Are' 的行
bash
echo "案例 3:过滤第一列大于 2 并且第二列等于 'Are' 的行"
echo "命令:awk '$1>2 && $2=="Are" {print $1,$2,$3}' log.txt"
awk '$1>2 && $2=="Are" {print $1,$2,$3}' log.txt
echo ""
解释:
$1>2 && $2=="Are"
是一个复合条件。其中$1>2
检查每行的第一列是否大于 2,$2=="Are"
检查每行的第二列是否等于字符串 "Are"。只有当这两个条件同时满足时,该行才符合要求。{print $1,$2,$3}
是当行满足复合条件时执行的操作,即输出满足条件的行的第一列、第二列和第三列。awk
在读取log.txt
文件的每一行时,会依次检查每行是否满足这个复合条件。在我们的示例数据中,只有 "3 Do you like awk" 这一行中,第一列 "3" 大于 2,第二列 "Do" 并不等于 "Are",不满足条件;而 "10 There are orange,apple,mongo" 同样不满足。只有 "3 Are you" 这种形式(假设原始数据存在)才会满足条件并被输出。
5. 删除测试文件
在完成所有案例的演示后,为了保持环境整洁,可以删除测试文件 log.txt
。
bash
rm -f log.txt
解释 :rm -f log.txt
命令用于删除名为 log.txt
的文件。-f
选项表示强制删除,即使文件只读或者不存在也不会提示错误信息。
使用方法
- 将上述代码分别保存为不同的脚本文件(如果需要单独运行每个案例),或者保存为一个完整的脚本文件(例如
filter_awk_demo.sh
)。 - 为脚本文件添加执行权限:
chmod +x [脚本文件名]
。 - 运行脚本:如果是分开保存的脚本文件,逐个运行;如果是保存为一个完整的脚本文件,直接运行
./filter_awk_demo.sh
。
这样,你可以清晰地看到每个 awk
过滤条件的具体操作和输出结果。
内建变量
内建变量使用案例
以下是基于表格中的内置变量编写的一些简单代码案例:
1. 创建测试文件
首先,创建一个简单的测试文件用于演示。假设创建一个名为 test.txt
的文件,内容如下:
bash
#!/bin/bash
# 创建测试文件
echo "line1 word1 word2
line2 word3 word4
line3 word5 word6" > test.txt
2. 使用变量 $1
(这里对应表格中的 Sn
,假设 FS
为空格)
- 案例:打印每行的第一个字段。
- 代码:
bash
echo "案例:打印每行的第一个字段"
awk '{print $1}' test.txt
echo ""
- 解释 :
$1
表示每行按默认分隔符(这里假设是空格,对应表格中的FS
)分割后的第一个字段。awk
会逐行读取test.txt
文件,并输出每行的第一个字段,即"line1"、"line2"、"line3"。
3. 使用变量 $0
(对应表格中的 S0
)
- 案例:打印完整的输入记录(整行)。
- 代码:
bash
echo "案例:打印完整的输入记录"
awk '{print $0}' test.txt
echo ""
- 解释 :
$0
代表完整的一行。awk
会逐行读取test.txt
文件并原样输出每行内容,即"line1 word1 word2"、"line2 word3 word4"、"line3 word5 word6"。
4. 使用变量 ARGC
- 案例:在脚本中传递参数并获取参数数量。
- 代码:
bash
#!/bin/bash
# 创建测试文件
echo "line1 word1 word2
line2 word3 word4
line3 word5 word6" > test.txt
# 使用 awk 并传递参数
awk -v arg1=value1 -v arg2=value2 'BEGIN{print ARGC}' test.txt
echo ""
- 解释 :
ARGC
表示命令行参数的数量。在这个案例中,我们通过-v
选项给awk
传递了两个参数(arg1
和arg2
),再加上默认的文件名参数(test.txt
),所以ARGC
的值为 3。BEGIN
块在处理文件内容之前执行,这里用于打印ARGC
的值。
5. 使用变量 ARGV
- 案例:在脚本中传递参数并查看参数数组。
- 代码:
bash
#!/bin/bash
# 创建测试文件
echo "line1 word1 word2
line2 word3 word4
line3 word5 word6" > test.txt
# 使用 awk 并传递参数
awk -v arg1=value1 -v arg2=value2 'BEGIN{for(i = 0; i < ARGC; i++) print ARGV[i]}' test.txt
echo ""
- 解释 :
ARGV
是包含命令行参数的数组。在这个案例中,我们通过-v
选项传递了两个参数,再加上默认的文件名参数。BEGIN
块中的循环用于逐个打印ARGV
数组中的元素,即程序名(通常是awk
)、arg1=value1
、arg2=value2
和test.txt
。
6. 使用变量 FILENAME
- 案例:打印当前文件名。
- 代码:
bash
echo "案例:打印当前文件名"
awk '{print FILENAME}' test.txt
echo ""
- 解释 :
FILENAME
表示当前文件名。awk
在处理test.txt
文件时,会逐行输出文件名test.txt
。
7. 使用变量 NR
- 案例:打印行号。
- 代码:
bash
echo "案例:打印行号"
awk '{print NR, $0}' test.txt
echo ""
- 解释 :
NR
表示已经读出的记录数,即行号(从1开始)。awk
会逐行读取test.txt
文件,并输出每行的行号和整行内容,例如"1 line1 word1 word2"、"2 line2 word3 word4"、"3 line3 word5 word6"。
8. 使用变量 NF
- 案例:打印每行的字段数。
- 代码:
bash
echo "案例:打印每行的字段数"
awk '{print NF}' test.txt
echo ""
- 解释 :
NF
表示一条记录的字段数目。awk
会逐行读取test.txt
文件,并输出每行的字段数,这里每行都有3个字段,所以会输出"3"、"3"、"3"。
9. 删除测试文件
在完成所有案例演示后,删除测试文件:
bash
rm -f test.txt
使用方法
- 将上述每个案例的代码分别保存为独立的脚本文件(例如
case1.sh
、case2.sh
等)。 - 赋予每个脚本文件执行权限:
chmod +x [脚本文件名]
。 - 逐个运行脚本:
./[脚本文件名]
。
这样可以清晰地看到每个变量在 awk
中的应用和效果。
以下是对这些awk
命令用法的优化讲解:
1. 创建测试文件
首先创建一个名为log.txt
的测试文件,用于演示各种awk
操作。
bash
#!/bin/bash
# 创建测试文件log.txt并写入示例数据
echo "2 this is a test
3 Do you like awk
This's a test
10 There are orange,apple,mongo" > log.txt
2. 案例1:输出第二列包含"th",并打印第二列与第四列
bash
echo "案例1:输出第二列包含'th',并打印第二列与第四列"
echo "命令:awk '$2 ~ /th/ {print $2,$4}' log.txt"
awk '$2 ~ /th/ {print $2,$4}' log.txt
echo ""
解释:
- 在
awk
中,$2
表示每行按默认分隔符(空格或制表符)分割后的第二列。 ~
是匹配操作符,用于检查第二列是否匹配后面的正则表达式模式。/th/
是正则表达式模式,表示要查找包含"th"的字符串。{print $2,$4}
表示当第二列匹配"th"时,打印第二列和第四列。在示例数据中,满足条件的是"this a"。
3. 案例2:输出包含"re"的行
bash
echo "案例2:输出包含're'的行"
echo "命令:awk '/re/ ' log.txt"
awk '/re/ ' log.txt
echo ""
解释:
- 这里的
/re/
是一个正则表达式模式。在awk
中,如果只给出正则表达式模式而没有指定操作,默认操作是打印整行。 - 所以
awk
会逐行检查log.txt
中的每一行,只要该行包含"re",就会输出该行。在示例数据中,符合条件的行是"3 Do you like awk"和"10 There are orange,apple,mongo"。
4. 案例3:忽略大小写
bash
echo "案例3:忽略大小写"
echo "命令:awk 'BEGIN{IGNORECASE=1} /this/' log.txt"
awk 'BEGIN{IGNORECASE=1} /this/ ' log.txt
echo ""
解释:
BEGIN{IGNORECASE=1}
是awk
的特殊块和变量设置。BEGIN
块在处理文件内容之前执行,IGNORECASE
是awk
的一个变量,当设置为1时,表示在进行模式匹配时忽略大小写。/this/
是正则表达式模式,在忽略大小写的情况下查找包含"this"的行。在示例数据中,符合条件的行是"2 this is a test"和"This's a test"。
5. 案例4:模式取反
bash
echo "案例4:模式取反"
echo "命令:awk '$2!~ /th/ {print $2,$4}' log.txt"
awk '$2!~ /th/ {print $2,$4}' log.txt
echo ""
解释:
$2!~ /th/
是模式取反操作。!~
表示不匹配,即检查第二列是否不包含"th"。{print $2,$4}
表示当第二列不包含"th"时,打印第二列和第四列。在示例数据中,符合条件的结果是"Are like"、"a"和"There orange,apple,mongo"。
6. 另一种模式取反方式
bash
echo "案例5:另一种模式取反方式"
echo "命令:awk '!/th/ {print $2,$4}' log.txt"
awk '!/th/ {print $2,$4}' log.txt
echo ""
解释:
!/th/
是对整个行进行模式取反操作。它检查整行是否不包含"th"。{print $2,$4}
表示当整行不包含"th"时,打印第二列和第四列。在示例数据中,结果与案例4相同。
7. 删除测试文件
在完成所有案例演示后,为了保持环境整洁,删除测试文件。
bash
rm -f log.txt
使用方法
- 将上述代码保存为一个脚本文件,例如
awk_regex_demo.sh
。 - 为脚本文件添加执行权限:
chmod +x awk_regex_demo.sh
。 - 运行脚本:
./awk_regex_demo.sh
,观察每个案例的输出结果。
通过以上优化后的内容,可以更清晰地理解和掌握awk
中与正则表达式和字符串匹配相关的操作。
awk脚本练习
关于 awk 脚本,我们需要注意两个关键词 BEGIN 和 END。
BEGIN{ 这里面放的是执行前的语句 }
END {这里面放的是处理完所有的行后要执行的语句 }
{这里面放的是处理每一行时要执行的语句}
假设有这么一个文件(学生成绩表):
bash
$ cat score.txt
Marry 2143 78 84 77
Jack 2321 66 78 45
Tom 2122 48 77 71
Mike 2537 87 97 95
Bob 2415 40 57 62
我们的 awk 脚本如下:
bash
$ cat cal.awk
#!/bin/awk -f
#运行前
BEGIN {
math = 0
english = 0
computer = 0
printf "NAME NO. MATH ENGLISH COMPUTER TOTAL\n"
printf "---------------------------------------------\n"
}
#运行中
{
math+=$3
english+=$4
computer+=$5
printf "%-6s %-6s %4d %8d %8d %8d\n", $1, $2, $3,$4,$5, $3+$4+$5
}
#运行后
END {
printf "---------------------------------------------\n"
printf " TOTAL:%10d %8d %8d \n", math, english, computer
printf "AVERAGE:%10.2f %8.2f %8.2f\n", math/NR, english/NR, computer/NR
}