如何将字符串插入到文本变量的指定位置

如何将字符串插入到文本变量的指定位置

我找到了很多字符串操作教程,但不知道如何将它们应用到我的特定情况。我需要插入(而不是替换)一个字符串变量单词到文本变量中文本使用任一方法(不能依赖于行编号,变量操作优于读/写文件):

  1. 在匹配的字符串之前,或者
  2. 在特定索引(字节位置)

    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/// 内容运行文本数据就很简单了。

相关内容