我读了很多接近的问题,但没有找到解决我的问题的方法。
我有一个具有当前结构的文本文件:
## 誰 <!--QR2Y;1;2023-04-18-->
だれ
quelqu'un, qui, quel
田中さんてだれですか。
« Qui est ce M. Tanaka ? »
## 歌う <!--T2B7;1;2023-04-18-->
うたう
chanter, réciter
ピアノに合わせて歌う。
« Chanter accompagné d'un piano. »
目的是交换和重新排序信息:
- 获取以 开头的行中的日语单词,
##
并将其替换为后两行。 - 删除此行两行后
- 并将这个日语单词放在修改后的
##
行下
为了得到这个结果
## quelqu'un, qui, quel <!--QR2Y;1;2023-04-18-->
誰
だれ
田中さんてだれですか。
« Qui est ce M. Tanaka ? »
## chanter, réciter <!--T2B7;1;2023-04-18-->
歌う
うたう
ピアノに合わせて歌う。
« Chanter accompagné d'un piano. »
结构总是相同的。可变部分是<!--X0X0;0;000-00-00-->
始终变化的部分,有时根本不存在。
这似乎sed
是一个解决方案,但我在文档中有点迷失......
答案1
解决方案与awk
- 使用同一文件进
awk
纸两次 - 在第一次运行中:
- 如果
##
找到,则将jw
(日语单词)和对应的fw
(法语单词)保存为数组,并以行号 (NR
) 作为索引。
- 如果
- 在第二次运行中:
- 检查行号是否存在,
fw
然后用法语单词替换日语单词,然后打印相应的日语单词。 - 打印除带有我们刚刚放置的法语单词的行之外的所有行。
- 检查行号是否存在,
awk '
NR == FNR && /^##/ { jw[NR]=$2; nr=NR; }
NR == nr+2 {fw[NR-2]=$0}
NR>FNR {
if(FNR in fw) { $2 = fw[FNR]; print; print jw[FNR]; }
else { if (!(FNR-2 in fw)) print; }}
' file file
输出:
## quelqu'un, qui, quel <!--QR2Y;1;2023-04-18-->
誰
だれ
田中さんてだれですか。
« Qui est ce M. Tanaka ? »
## chanter, réciter <!--T2B7;1;2023-04-18-->
歌う
うたう
ピアノに合わせて歌う。
« Chanter accompagné d'un piano. »
答案2
这是一个单遍解决方案:
awk '/^##/ {hdr=$0; j1=$2; getline; j2=$0; getline; fr=$0;
sub(/## [^<]+/, "## " fr " ", hdr); print hdr; print j1; print j2; next } 1' input
- 这将通过起始模式识别标题行
##
并将其存储在变量中hdr
。 - 然后,它将提取第一个日语部分
j1
作为该行的第二个空格分隔字段(我假设它们不包含空格)。 - 它将读取下一行并将其完全缓冲为第二个日语部分
j2
。 - 它将再次读取下一行并将其缓冲为法语翻译
fr
。 - 然后,它将用法语翻译替换缓冲标头中的第一个日语部分,打印修改后的标头和两个日语部分,每个部分各占一行。然后它会跳到下一行执行。
1
由于规则块外部(看似杂散),所有其他行均不加修改地打印。
答案3
在 1 遍中使用任何支持多字节字符的 awk(对于日语单词):
awk '
BEGIN { RS=""; ORS="\n\n"; FS=OFS="\n" }
/^##/ { split($1,a," "); $1=a[1] " " $3 " " a[3]; $3=$2; $2=a[2] }
1' file
## quelqu'un, qui, quel <!--QR2Y;1;2023-04-18-->
誰
だれ
田中さんてだれですか。
« Qui est ce M. Tanaka ? »
## chanter, réciter <!--T2B7;1;2023-04-18-->
歌う
うたう
ピアノに合わせて歌う。
« Chanter accompagné d'un piano. »
如果记录之间没有空行,因此RS=""
不起作用,那么您可以这样做(仍然是 1 遍,只是为每个##
块缓冲 3 行):
$ cat tst.awk
BEGIN { FS=OFS="\n" }
/^##/ { lineNr=1; buf = $0; next }
lineNr { lineNr++; buf = buf RS $0 }
lineNr == 3 {
$0 = buf
split($1,a," "); $1=a[1] " " $3 " " a[3]; $3=$2; $2=a[2]
lineNr = 0
}
!lineNr
$ awk -f tst.awk file
## quelqu'un, qui, quel <!--QR2Y;1;2023-04-18-->
誰
だれ
田中さんてだれですか。
« Qui est ce M. Tanaka ? »
## chanter, réciter <!--T2B7;1;2023-04-18-->
歌う
うたう
ピアノに合わせて歌う。
« Chanter accompagné d'un piano. »
答案4
和perl
:
perl -00pe 's/^(##\s*)(.*?)(\s*<!--.*-->\n)(.*)\n(.*)/$1$5$3$2\n$4/' your-file