文本处理
文本处理
awk
awk
是一种用于文本处理和数据抽取的强大命令行工具。它基于模式匹配和动作执行的原则,允许您在文本文件中查找特定模式并执行相应的操作。
awk
的基本语法为:
awk 'pattern { action }' input_file
以下是一些常见的 awk
选项及案例说明
列抽取
从文本文件中抽取指定的列。
awk '{print $2}' data.txt
这个命令从名为 data.txt
的文本文件中,每行提取第二列的数据并输出。
$2
表示第二列。列的计数是从 1 开始的。
$0
表示整行内容。
特殊变量
awk 'END {print NR}' file.txt
这个命令在名为 file.txt
的文件结束时输出文件的总行数。
-
NR
表示当前行号NF
表示当前行中字段(或列)的数量- **
FS
(字段分隔符)**:表示字段之间的分隔符。默认情况下,FS
的值是空格或制表符(\t
)。你可以使用-F
命令行选项来改变字段分隔符。- **
RS
(记录分隔符)**:表示记录(行)之间的分隔符。默认情况下,RS
的值是换行符(\n
)。你可以使用-F
命令行选项来改变记录分隔符。- **
OFS
(输出字段分隔符)**:表示输出时字段之间的分隔符。默认情况下,OFS
的值与FS
相同。- **
ORS
(输出记录分隔符)**:表示输出时记录之间的分隔符。默认情况下,ORS
的值是换行符(\n
)。- **
FILENAME
**:表示当前正在处理的文件的名称。
自定义分隔符
awk -F ':' '{print $1, $7}' /etc/passwd
使用冒号作为字段分隔符,提取 /etc/passwd
文件的第一列(用户名)和第七列(用户的登录Shell)。
默认使用空格作为字段分隔符,
-F
选项用于指定字段分隔符。
自定义输出分隔符
awk 'BEGIN {OFS="\t"} {print $1, $2}' data.txt
设置输出分隔符为制表符,然后每行输出第一、第二和第三列的数据,用制表符分隔。
默认使用空格作为输出分隔符。可以使用内置的
OFS
变量来自定义输出分隔符。
自定义变量参数
awk -v OFS=":" '{print $1, $2, $3}' data.txt
设置输出分隔符,输出的每列字段之间用:
分割
awk -v math_weight=0.6 -v eng_weight=0.4 '{ total = ($2 * math_weight) + ($3 * eng_weight); print $1, "Total:", total }' grades.txt
设置数学成绩的权重为0.6,英语成绩的权重为0.4,然后计算每个学生的总成绩
格式化输出
awk '{printf "Name: %-10s Age: %2d\n", $1, $3}' data.txt
将名为 data.txt
的文件中的第一列(姓名)和第三列(年龄)格式化输出,确保名字占据10个字符的宽度,年龄占据2个字符的宽度。
-
%
:表示格式化字符串的起始标记。-
-
:表示左对齐文本。如果没有-
,则默认是右对齐。-
10
:表示字段的宽度。在这里,它指定字符串字段占据的总宽度为 10 个字符。-
s/d
:表示字符串的数据类型。
初始块/结束块
只在第一次和最后一次执行
awk 'BEGIN {
print "Student Scores:"
print "----------------"
}
{
print "Student:", $1, "Scores:", $2
}
END {
print "----------------"
print "End of Student Scores"
}' student_scores.txt
使用 BEGIN
块在处理开始时输出提示信息,然后在每行数据处理时只输出每个学生的名字和成绩字段。最后,我们使用 END
块在处理结束时输出结束信息。
BEGIN
块来在处理开始时执行一些操作;END
块来在处理结束时执行一些操作。
条件结构
awk '{
if ($2 > 50000) {
category = "High"
} else if ($2 > 30000) {
category = "Medium"
} else {
category = "Low"
}
print $1, ":", category
}' employees.txt
使用 if
、else if
和 else
条件语句根据薪水水平将员工分为不同的分类,并打印出结果。
循环结构
for
循环
awk 'BEGIN { sum = 0 } { sum += $1 } END { print "Sum:", sum }' numbers.txt
BEGIN
部分用于初始化变量 sum
,然后每行的数字会被加到 sum
中,最后 END
部分打印出总和。
awk '{
total = 0
for (i = 2; i <= NF; i++) {
total += $i
}
print $1, "Total:", total
}' student_scores.txt
遍历从第二个字段开始的每个字段,并将它们相加以计算学生的总分。然后,我们使用 print
命令输出每个学生的姓名和总分。
while循环
awk '{
total += $2
count++
}
END {
avg = total / count
print "Average:", avg
print "Students above average:"
while (getline < "scores.txt" > 0) {
if ($2 > avg) {
print $1, $2
}
}
}' scores.txt
在while循环中,使用 getline 函数从文件中逐行读取数据,然后通过条件语句判断分数是否高于平均分,并输出相应的学生信息。
行处理
awk '/^host1/' logfile.txt
输出所有以 "host1" 开头的日志记录
# -i 忽略大小写
awk '/error/i' logfile.txt
# 设置参数,忽略大小写
awk 'BEGIN {IGNORECASE=1} /error/' logfile.txt
# 将内容转换为小写,然后使用 ~(匹配运算符)进行正则匹配
awk 'tolower($0) ~ /error/ ' logfile.txt
匹配日志中所有包含error的行,忽略大小写
可以在模式部分使用斜杠
/
包裹正则表达式。
关联数组
awk '!seen[$0]++' input.txt
去重,只输出第一次出现的行
- 关联数组在
awk
中可以用于统计每行出现的次数,是因为它们提供了一种将键(索引)与值关联起来的方式。在这种情况下,数组的键是文本行的内容,而值是该行出现的次数。
awk '{ seen[$0]++ } END { for (record in seen) print record, "Count:", seen[record] }' input.txt
统计每行出现的次数
个性化定制搜索模式
假设您有一个名为 data.txt
的文本文件,其中包含以下内容:
this is wang ,not wan
that is chen, not che
this is chen ,and wang ,not wan che
提取is后面的第一个单词,和not 后面的第一个单词
awk '{match($0,/.+is([^,]+).+not(.+)/,a);print a[1],a[2]}' test
a[1]代表第一个()的内容,a[2]代表第二个()的内容,以此类推
grep
grep
是一个在 Unix-like 系统上常用的命令行工具,用于在文本文件中搜索指定的字符串模式,并返回匹配的行。它的名字来自于 "Global Regular Expression Print",表示它的原始目的是全局地搜索正则表达式并打印匹配的结果。
grep
的基本语法为:
grep [options] pattern [file ...]
以下是一些常见的 grep
选项及案例说明:
基本用法
在单个文件中搜索指定字符串模式,并返回匹配的行。
grep "pattern" filename
在多个文件中搜索
在多个文件中搜索指定字符串模式。
grep "pattern" file1 file2
递归搜索
在指定目录及其子目录中递归搜索。
grep -r "pattern" directory
忽略大小写
不区分大小写地搜索。
grep -i "pattern" filename
显示行号
显示匹配行的行号。
grep -n "pattern" filename
显示匹配的上下文
显示匹配行及其上下文的内容。
grep -C 2 "pattern" filename
只显示匹配的计数
显示匹配的行数而不显示具体内容。
grep -c "pattern" filename
反向搜索
显示不包含指定字符串模式的行。
grep -v "pattern" filename
使用正则表达式
使用正则表达式进行更复杂的模式匹配。
grep -E "regex pattern" filename
sed
sed
(Stream Editor)是一个流式文本编辑器,用于在输入流中进行文本替换、转换和编辑。它主要用于在命令行中进行文本处理,支持各种文本操作,如替换、插入、删除、打印等。sed
使用基于正则表达式的模式匹配来定位和操作文本。
以下是一些常用的 sed
案例介绍:
替换文本内容
sed 's/old_text/new_text/' input.txt
这会在输入文件中将第一个匹配的 "old_text" 替换为 "new_text"
上述命令仅在标准输出中显示结果,不会更改原始文件。
保存修改到新文件
sed 's/pattern/replacement/' input.txt > output.txt
将修改后的内容输出到一个新文件中
编辑原文件
sed -i 's/pattern/replacement/' input.txt
使用 -i
参数可以直接在原始文件上进行编辑,而不需要创建新文件
替换所有匹配
sed 's/old_text/new_text/g' input.txt
加上 g
标志将替换所有匹配的 "old_text"。
只打印匹配的行
sed -n '/pattern/p' input.txt
-n
参数表示只输出匹配的行,/pattern/p
表示匹配包含 "pattern" 的行并打印出来。
删除匹配的行
sed '/pattern/d' input.txt
删除包含 "pattern" 的行。
插入新行
# 在第二行之前插入一行文本
sed '2i\New line to insert' input.txt
# 在第二行之后插入一行文本
sed '2a\New line to after' input.txt
在固定的行前后插入数据
# 在包含hello的上一行插入up
sed -i '/hello/i\up' input.txt
# 在包含hello的下一行插入down
sed -i '/hello/a\down' input.txt
在匹配的行前后插入数据,有多个匹配行,那么在每一行上面或者下面都插入内容
# 在最后一行之后追加一行文本
sed '$a\New line to append' input.txt
# 最后一行之前追加一行文本
sed '$i\New line to append' input.txt
在文件最后一行的前后插入数据, $
表示最后一行。
使用正则表达式匹配
sed 's/[0-9]\+$/REPLACEMENT/' input.txt
在每一行的结尾匹配一个或多个数字并替换为 "REPLACEMENT"