Linux sed';s';N';命令间歇工作
下面是我要格式化的文本块示例:Linux sed';s';N';命令间歇工作,linux,bash,sed,Linux,Bash,Sed,下面是我要格式化的文本块示例: <tr><td></td><td>tear a cat in, to make all split.</td><td></td></tr> <tr><td></td><td class="tdci">The raging rocks</td><td></td></tr> &l
<tr><td></td><td>tear a cat in, to make all split.</td><td></td></tr>
<tr><td></td><td class="tdci">The raging rocks</td><td></td></tr>
<tr><td></td><td class="tdci">The foolish Fates.</td></tr>
<tr><td></td><td>This was lofty! Now name the rest of the players.</td><td></td></tr>
撕开一只猫,把所有的东西都撕开。
汹涌的岩石
愚蠢的命运。
这是崇高的!现在说出其余球员的名字。
在脚本中使用这两个“sed”命令:
sed -ri '/^<tr><td><\/td><td>/N;s/(\n<tr><td><\/td><td class="tdci">)/\n<tr><td>\ <\/td><\/tr>\1/' "$f" #insert table row with empty data fields (blank line) above first line with 'class="tdci"'
sed -ri '/^<tr><td><\/td><td class="tdci">/N;s/(\n<tr><td><\/td><td>)/\n<tr><td>\ <\/td><\/tr>\1/' "$f" #insert table row with empty data fields (blank line) after last line with 'class="tdci"'
sed-ri'/^/N;s/(\n)/\n\\1/“$f”#在第一行上方插入带有空数据字段(空行)的表行,并使用“class=”tdci“'
sed-ri'/^/N;s/(\n)/\n\\1/“$f”#在带有“class=”tdci“的最后一行之后插入数据字段为空的表行(空行)'
结果如下:
<tr><td></td><td>tear a cat in, to make all split.</td><td></td></tr>
<tr><td> </td></tr>
<tr><td></td><td class="tdci">The raging rocks</td><td></td></tr>
<tr><td></td><td class="tdci">The foolish Fates.</td></tr>
<tr><td></td><td>This was lofty! Now name the rest of the players.</td><td></td></tr>
撕开一只猫,把所有的东西都撕开。
汹涌的岩石
愚蠢的命运。
这是崇高的!现在说出其余球员的名字。
因此,第一个sed
命令通过使用class=“tdci”
在第一行上方插入一个空表行来工作,但是几乎相同的第二个sed
命令意味着在最后一行之后插入一个空表行,而使用class=“tdci”
则不起作用
我通常为vim保存这些编辑,在多行之间编辑,因为我从来没有遇到过类似命令的问题,但出于某种原因,sed
“N;s/
对我来说总是一帆风顺,就像在本例中,一个实例可以正常工作,而另一个实例则不行。在运行这些命令之前,脚本将删除所有前导/尾随空格和任何Winblowz回车(\r
)
由于我有大量的文件要编辑,如果有人能看到任何明显的我做错了的事情,我当然更愿意在脚本中运行
其他详情:
抱歉,我忘了提到我正在Linux(Debian stable)中运行
sed
从小开始!下面是一个更简单的测试用例:
a1
b1
b2
a2
下面是您针对该测试用例翻译的代码,尝试在第一个“b”之前插入c1
,在最后一个“b”之后插入c2
:
sed -ri '/a/N; s/(\nb)/\nc1\1/' file
sed -ri '/b/N; s/(\na)/\nc2\1/' file
正如您所说,第一个命令似乎起作用:
a1
c1
b1
b2
a1
第二个没有,只给出与上面相同的结果,而不是插入c2
以下是您可能认为会发生的情况,粗体部分不正确:
a1
c1
b1
被读取。
- 它与
匹配,/b/
用b2
读取李>N
- 它与
不匹配李>\na
已打印b1
b2
被再次读取。
- 它与
匹配,/b/
用a
读取N
- 它与
匹配<代码>c2追加\na
b2\nc2\na已打印
a1
c1
b1
被读取。
- 它与
匹配,/b/
用b2
读取李>N
- 它与
不匹配李>\na
已打印b1\nb2
a2
被读取和打印,因为上面已经读取了b2
李>
这是一个有效的命令:
sed -ri '/b/ { :b; N; s/\na/\nc2&/; te; P; D; bb; }; :e;' file
在伪代码中——注释中大致对应sed部分——这是:
if (input.matches("b")) { // /b/ {
while(true) { // :b
input += "\n" + readline(); // N
if(input.matches("\na")) { // s/\na/ ..
input = input.replace("(\na)", "\nc2\1"); // .. \nc2&/
goto exit; // te
}
print(input.substring(0, input.indexOf('\n')); // P
input = input.substring(input.indexOf('\n') + 1); // D
} // bb
} // }
:exit // :e
翻译回您的数据:
sed -ri '/^<tr><td><\/td><td class="tdci">/ { :b; N; s/(\n<tr><td><\/td><td>)/\n<tr><td>\ <\/td><\/tr>\1/; te; P; D; bb; }; :e' "$f"
sed-ri'/^/{:b;N;s/(\N)/\N\\1/;te;P;D;bb;};:e“$f”
演示如何使用sed
执行此操作
然而,sed
在遇到这些本质上有点程序性的问题时可能会让人大吃一惊,因此这里有一个awk
解决方案,可能更容易理解:
awk -v blockRegex='^<tr><td><\/td><td class="tdci">' \
-v lineToInsert='<tr><td>\ <\/td><\/tr>' \
'
# Print a line BEFORE the FIRST line matching `blockRegex`.
$0 ~ blockRegex { if (!afterFirst) {print lineToInsert; afterFirst=inBlock=1} }
# Print a line AFTER the LAST (contiguous) line matching `blockRegex`.
inBlock && $0 !~ blockRegex { print lineToInsert; afterFirst=inBlock=0 }
# Print the input line.
{ print }
' \
file
awk-v blockRegex='^'\
-v lineToInsert='\'\
'
#在匹配“blockRegex”的第一行之前打印一行。
$0~blockRegex{if(!afterFirst){print lineToInsert;afterFirst=inBlock=1}
#在与“blockRegex”匹配的最后一行(连续)后打印一行。
块内&&$0!~blockRegex{print lineToInsert;afterFirst=inBlock=0}
#打印输入行。
{print}
' \
文件
请注意,这可以进一步优化,但我想让它更简单,以澄清逻辑
作为变量传入(带有选项blockRegex
),以标识要插入的行前后的连续行块,要插入的行作为变量传入-v
lineToInsert
匹配感兴趣行块中的每一行,并打印要插入的行(如果它是块中的第一行),如状态变量$0~blockRegex
所示;状态变量afterFirst
表示当前行位于感兴趣的块内inBlock
匹配感兴趣块后的第一行并打印要插入的行,然后重置状态变量李>inBlock&&0!~blockRegex
只按原样打印输入行print
请注意,状态变量的使用依赖于
awk
中默认为0
(在布尔上下文中被视为false
;类似地,非零值的计算结果为true
)。有大量的HTML解析器和漂亮的打印机;利用这些。你在什么操作系统上这样做?sed的哪个版本?@devnull我很感激HTML的建议,但是让我们集中精力。我的问题是关于特定“sed”命令的行为;我试图处理的文本很可能是HTML以外的其他格式。@tog:wow!它是有效的,但老实说,我已经迷路了,必须开始阅读你们详细介绍的“sed”选项,以帮助了解如何和为什么;伟大的分析;伪代码缺少字符串替换逗号