我有大约一百个包含Latex片段的Markdown文件,如下所示:
<div latex="true" class="task" id="Task">
(@) Delete the fourth patterns from your .teach file and your .data files. Remember to change the second line in each so that Tlearn knows there are now only three patterns.
- They should look like [@fig:dataTeach]
</div>
我想用更容易阅读的伪标签替换<div>
标签,如下所示:
<task>
(@) Delete the fourth patterns from your .teach file and your .data files. Remember to change the second line in each so that Tlearn knows there are now only three patterns.
- They should look like [@fig:dataTeach]
</task>
如果我的所有<div>
标签都标记为“任务”,这将是微不足道的,但我有'journal'和'highlight'的类似div。我需要一个只有当前面的</div>
具有类或ID“任务”时才会将</task>
更改为<div>
的流程,同样适用于“journal”和“highlight”。
浏览了Stack Overflow一段时间后,我发现许多多行搜索和替换的例子几乎可以做我想做的事情,但语法(特别是对于sed)很难解开我无法适应它以上情况。我的下一个选择是写一个bash脚本逐行循环,但我觉得这可能太脆弱了。
干杯
伊恩
答案 0 :(得分:0)
这应该可以解决问题:
$msys\bin\sed -En "s/<div latex=\"true\" class=\"task\" id=\"Task\">/<task>/;T;{:a;N;s/<\/div>/<\/task>/;Ta;p;}" input.txt
如果您想要改编它们,这些是构建块:
{:a;
s/<\/div>/<\/task>/;Ta;
s/<div latex=\"true\" class=\"task\" id=\"Task\">/<task>/;T;
N;
p;}
$msys\bin\sed -En
答案 1 :(得分:0)
不需要循环。只需管道文件......
sed '/Task/s/<div.*>/<task>/g;s/<\/div>/<\/task>/g'
开头的 /Task
仅在sed
内编辑名称为Task
的行。
使用s/NAME/NEWNAME/
逐个替换某些文字
添加.*
将替换此时开始的所有文本。
最后但同样重要的是,g
代表全局,并会以这种方式编辑所有条目。
第二个命令(在;
之后)将</div>
替换为</task>
。它像以前一样是同一个命令的一部分。这次的不同之处在于/
(斜杠)将由sed
自己使用,如果不是其他明智的话!这可以通过\
(反斜杠)存档。
你走了。您文件的输出将如下所示....
<task>
(@) Delete the fourth patterns from your .teach file and your .data files. Remember to change the second line in each so that Tlearn knows there are now only three patterns.
- They should look like [@fig:dataTeach]
</task>
答案 2 :(得分:0)
以下awk
命令通常适用于以下假设:
所有开始和结束div
标签都在各自的行上。
属性全部使用"
- 引用。
新标记名称仅来自class
属性的值(如果规则更清晰,则可以推广)。
awk -F ' class="' '
/^<div / && NF > 1 { tag=$2; sub("\".*", "", tag); printf "<%s>\n", tag; next }
/^<\/div>/ && tag != "" { printf "</%s>\n", tag; tag=""; next }
1
' file
-F ' class="'
有效地将每一行拆分为之前(字段1,$1
)和之后(字段2,$2
)class
属性(如果存在)。因此,只有具有此类属性的行才会有多个字段(NF > 1
)。
处理开场div
代码:
模式/^<div / && NF > 1
仅匹配以(^
)<div
开头的行和(&&
)包含class
属性({{ 1}})
NF > 1
从第二个字段中提取tag=$2; sub("\".*", "", tag)
属性值,方法是替换第一个class
(属性值的结束"
)中的所有内容空字符串,仅在变量"
中有效保留属性值。
tag
将属性值打印为替换开始标记。
printf "<%s>\n", tag
跳过脚本的其余部分并移至下一个输入行。
处理结束next
代码:
div
与结束/^<\/div>/ && tag != ""
代码匹配,假设在前一个开始代码(div
)中找到class
属性值。
tag != ""
打印新的结束标记。
printf "</%s>\n", tag
重置最新的替换代码,以便任何后续的tag=""
元素都没有div
属性也不会被意外重命名。
class
跳过脚本的其余部分并移至下一个输入行。
所有其他行:
next
只是按原样打印所有其他行。 (1
是1
的常见Awk简写:模式{ print }
,解释为布尔值,按定义为true,没有关联操作的模式1
打印输入行默认情况下)。答案 3 :(得分:0)
这可能适合你(GNU sed):
v='task|journal|highlight'
sed -ri '/^<div/{:a;N;/^<\/div/M!ba;s/^<.*class="('$v')"[^>]*(.*<\/)div/<\1\2\1/}' file1 file2 file3 ...
这会将div
语句存储在模式空间中,然后根据预先设置的shell变量替换(或不替换)所需的值。
N.B。替代品存储在由v
|
中