我想在文件的每一行上查找一个字符串,如果它存在,则返回一个不同的特定字符串。
在发布解决方案后,此帖子已被编辑,以帮助更好地说明问题(因此一些较早的回复不再适用)
我有这个代码:
Numlines=$(grep "" -c File.txt)
for (( line=1; line<=$Numlines; line++ )) ; do
awk -v line="$line" 'NR==line ...???
我正在寻找的字符串是style-name="T
. 如果该字符串在 for 循环中的一行中,则返回T
. 中的行File.txt
可能包含类似的字符串style-name="T2"
,在这种情况下,我只想返回2
. 该字符串不在 中的每一行的相同位置File.txt
,所以我认为我不能在 中使用字段名称awk
。
IIRC,"/style-name\=\"T/"
应该提供匹配,但如果我在我的代码中使用它,它要么给我一个错误,要么什么都不返回。也许脚本会检查它是否可以产生匹配,如果可以,使用第二行代码来获取字符串,尽管我认为awk
可以通过单行代码完成它,一旦前驱代码被计算出来出去。
这是一个示例File.txt
:
<TEST1> <text:p text:style-name="P4">Hello<text:span text:style-name="T2">world</text:span></text:p>
<tyi.ggg> <text:p text:style-name="P9">Hi<text:span text:style-name="T16">there</text:span></text:p>
<TEST2> <text:p text:style-name="P540">0 <text:s/>oooh yeah<text:s text:c="2"/>kool-aid<text:s text:c="12"/>0:00</text:p>
第一行(第一次通过for
循环)的输出应该是 2。第二行(第二次通过for
循环)的输出应该是 16。第三行的输出应该是什么。
我使用以下文本作为示例(修改了 OP 提供的示例):
我想出了这种
grep
和sed
命令的组合,它可能不是最有效的,但相对容易理解:分解命令:
grep -n 'style-name="T' File.txt
style-name="T
添加匹配的行号。输出是:
grep -P -o '^\d+:<\w*>|style-name="T\d+'
使用先前的输出作为输入,并将行号与内部:<
和>
旁边的文本以及旁边的数字相匹配style-name="T
。每个匹配项都打印在新行中。输出是:
sed -z 's/style-name="//g; s/:/ /; s/\nT/ T/g'
使用先前的输出作为输入,并删除style-name="
和替换( ):
之前的换行符,并用一个空格后跟( ) 替换。T
\nT
T
T
输出是:
我看不到使用 shell 循环多次处理文件的任何价值。
在 GNU awk 中,您可以使用该函数将子模式捕获到数组中
match
。所以你可以简单地做:在常规 POSIX awk 中,该
match
函数没有此扩展功能,但您可以改用它的RSTART
andRLENGTH
来提取所需的子字符串:[如果由于某种未指定的原因,您必须在每次迭代中针对特定行号的 shell 循环中执行此操作,那么您可以将规则更改为
NR==line && match(...) {...}
]。如果您需要为每条记录提取多个 值,则可以将其包装在一个遍历ex 的循环中:
T#
match
$0
RSTART
要使用我之前展示的andRLENGTH
方法在非 GNU awk 中执行相同的操作,请将while
循环替换为: