我找到了很多字符串操作教程,但不知道如何将它们应用到我的特定情况。我需要插入(而不是替换)一个字符串变量单词到文本变量中文本使用任一方法(不能依赖于行编号,变量操作优于读/写文件):
- 在匹配的字符串之前,或者
在特定索引(字节位置)
text="mytextMATCHmytext" word="WORD" match="MATCH" # method1 - not working, because text is not a file sed '/$word/ i $match' text # method2 indx="${text%%$match*}" indx=${indx%:*} # leave only the byte index where match starts text="$text{0-$index-1}$word$text{$index-end}" # expected value of text: "mytextWORDMATCHmytext"
请帮忙弄清楚语法。如果能修复这两种方法就好了。还有其他方法吗?这文本包含 >1MB 的文本,因此,首选有效的方法。
答案1
要将文本插入j
变量中text
的位置p
(从零开始计数):
p=5
text="$(seq 10)" ## arbitrary text
text="${text:0:p}j${text:p}"
j
要在 中的匹配部分之前插入文本$match
:
text="${text%%${match}*}j${match}${text##*${match}}"
$text
这会拉出直到找到的前导部分$match
,然后添加j
,然后添加 ,然后添加直到找到的$match
尾部部分。希望只有一场比赛!$text
$match
$match
$text
答案2
正如您所说,如果您的数据位于变量而不是文件中,则无法sed
直接使用。然而,这仍然是满足您要求的简单方法;你只需要管道化它:
#!/usr/local/bin/bash
text="loremipsumNEEDLEdolorsitamet"
word="HAYSTALK"
match="NEEDLE"
echo "$text" | sed "s/$match/&$word/g"
示范输出:
$ ./369818.sh
loremipsumNEEDLEHAYSTALKdolorsitamet
答案3
您需要以下字符串操作例程才能可靠地执行该操作:
text_new=${text%%"${match}"*}${word}${text#*"${text%%"${match}"*}"}
# |------- A -------| |-B--| |------------ C -------------|
A
是匹配前部分,即匹配开始之前的字符串。- 它是通过以下方式生成的:站在字符串的末尾,看着字符串的开头,然后删除并包括最后一次看到的匹配文本。
B
是要插入的数据。C
是匹配后部分,即匹配结束后的字符串。- 它是通过以下方式生成的:站在字符串的开头,看向字符串的末尾,然后撕开并包括第一次看到步骤 A 的结果。
- 请注意,匹配字符串被引用以避免例程理解其中的任何元字符
bash
parameter expansion
。 - 适当考虑了匹配项在字符串中出现多次的可能性。左侧第一场比赛被替换。
- 带有换行符的字符串的大小写也会被处理。
塞德
match_esc=$(printf '%s\n' "$match" | sed -e 's|[][^\/.*$]|\\&|g' | sed -e 'H;1h;$!d;g;s/\n/\\n/g')
word_esc=$(printf '%s\n' "$word" | sed -e 's|[\&/]|\\&|g;$!s/$/\\/')
printf '%s\n' "$text" | sed -e 'H;1h;$!d;g;'"s/$match_esc/$word_esc&/"''
- 该
sed
方法更加迂回,因为我们必须确保所有对输入文本有意义sed
并且出现在输入文本中的字符都应该保持沉默。另一个复杂程度是这些字符对于 sed 的 s/// 命令的 LHS 和 RHS 是不同的。 - 下一步是识别这些字符,然后将它们静音。
- 之后,使用通常的 sed s/// 内容运行文本数据就很简单了。