![](/img/trans.png)
[英]How can I replace lines in a text file with lines from another file based on matching pattern?
[英]How can i reoder lines in a text file based on a pattern?
我有一个包含 4 行批次的文本文件,每个批次的第一行位于正确的位置,但接下来的 3 行并不总是按正确的顺序排列。
name cat
label 4
total 5
value 4
name dog
total 4
label 3
value 6
name cow
value 6
total 1
label 4
name fish
total 3
label 5
value 6
我希望每个 4 行批次采用以下格式:
name cat
value 4
total 5
label 4
所以输出将是:
name cat
value 4
total 5
label 4
name dog
value 6
total 4
label 3
name cow
value 6
total 1
label 4
name fish
value 6
total 3
label 5
该文件总共包含数千行,所以我想构建一个命令来处理这 3 行的所有潜在顺序,如果格式不正确,则重新排列它们。
我知道我可以使用 awk 搜索以特定字符串开头的行,然后重新排列它们:
awk '$1 == "value" { print $3, $4, $1, $2; next; } 1'
但是我不知道如何实现类似的处理多行的东西。
我怎样才能做到这一点?
通过将RS
设置为空字符串,由至少一个空行分隔的每个文本块被视为单个记录。 从那里可以轻松捕获每个键值对并按所需顺序输出它们。
BEGIN {RS=""}
{
for (i=1; i<=NF; i+=2) a[$i] = $(i+1)
print "name", a["name"] ORS \
"value", a["value"] ORS \
"total", a["total"] ORS \
"label", a["label"] ORS
}
$ awk -f a.awk file
name cat
value 4
total 5
label 4
name dog
value 6
total 4
label 3
name cow
value 6
total 1
label 4
name fish
value 6
total 3
label 5
你能不能试试以下。
awk '
/^name/{
if(name){
print name ORS array["value"] ORS array["total"] ORS array["label"] ORS
delete array
}
name=$0
next
}
{
array[$1]=$0
}
END{
print name ORS array["value"] ORS array["total"] ORS array["label"]
}
' Input_file
编辑:添加 Kvantour 先生建议的上述精炼解决方案。
awk -v OFS="\n" '
(!NF) && ("name" in a){
print a["name"],a["value"],a["total"],a["label"] ORS
delete a
next
}
{
a[$1]=$0
}
END{
print a["name"],a["value"],a["total"],a["label"]
}
' Input_file
最简单的方法如下:
awk 'BEGIN{RS=""; ORS="\n\n"; FS=OFS="\n"}
{ for(i=1;i<=NF;++i) { k=substr($i,1,index($i," ")-1); a[k]=$i } }
{ print a["name"],a["value"],a["total"],a["label"] }' file
这是如何运作的?
awk 知道记录和字段的概念。 文件被分割成记录,其中连续的记录被记录分隔符RS
分割。 每条记录都拆分为字段,其中连续的字段由字段分隔符FS
拆分。 默认情况下,记录分隔符RS
设置为 <newline> 字符 ( \\n
),因此每条记录都是一行。 记录分隔符的定义如下:
RS
:的字符串值的第一个字符RS
应输入记录分隔符; 默认为 <newline>。 如果RS
包含多个字符,则结果未指定。 如果RS
为空,则记录由由 <newline> 加上一个或多个空行组成的序列分隔,前导或尾随空行不应在输入的开头或结尾导致空记录,并且 <newline> 应无论FS
的值是什么,始终是字段分隔符。
因此,使用您提供的文件格式,我们可以根据RS=""
和字段分隔符 `FS="\\n" 定义记录。
每条记录看起来都简化为:
key1 string1 << field $1
key2 string2 << field $2
key3 string3 << field $3
key4 string4 << field $4
...
keyNF stringNF << field $NF
当 awk 读取一条记录时,我们首先通过将所有key-value
对存储在数组a
解析它。 之后,我们要求打印我们觉得有趣的值。 为此,我们需要定义输出字段分隔符OFS
和输出记录分隔符ORS
。
在 Vim 中,您可以使用逆序排序对文件进行分段sort!
:
for i in range(1,line("$"))
/^name/+1,/^name/+3sort!
endfor
从 shell 发出的相同命令:
$ ex -s '+for i in range(1,line("$"))|/^name/+1,/^name/+3sort!|endfor' '+%p' '+q!' inputfile
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.