如何在 sed 中使用 () 内的换行符?

如何在 sed 中使用 () 内的换行符?

当我想替换时,Dot

Dot
##empty line##

我这样做:

sed 's/Dot/Dot\
/g'

是的,一个字面上的新行,这就是它在 BSD 上的工作方式sed。但是,当sed位于括号内时,我不能做同样的事情。命令示例:

lol=$(echo $varcontaining something | sed 's/Dot/Dot\
/g')

因为它只会将 is 替换为 . (空白)

答案1

Stackoverflow 问答中提到的这些方法怎么样:如何在 BSD sed 中使用换行符替换?:

sed -e 's/ /\'$'\n/g'

或者提到另一种方法,将换行符放入变量中,如下所示:

cr="
"

然后使用变量:

sed "s/ /\\${cr}/g"

答案2

Shell 删除尾随的换行符。常见的解决方法是在命令替换的最后添加一个字符,然后将其删除。

x=$( echo a; echo ; echo :)
echo "${x%:}"

答案3

据我认为,最有效的方法可能是使用eval.如果您希望从 shell 扩展中获取文字值,那么获取它们的最直接方法是从文字输入中获取它们,而从 shell 的输出中获取该值的唯一方法是将其重新输入。

使用'硬引号通常是最简单的。'硬引用字符串的简单引用规则'是它不能包含硬引用 - 在这种上下文中解释硬引用的唯一方法是将 2 个或更多引用的字符串连接在一起,例如......

VAR='string'\''more string'

这样,第一个带引号的字符串在第二个引号处结束,第二个带引号的字符串只是一个反斜杠转义的硬引号,第三个是第四个硬引号。

那么如果你是我我可能会做什么...

eval "lol='$(nl='\
';    printf %s\\n "$lol" |
      sed "s/Dot/&$nl/g
           s/'"'/&\\&&/g
          $s/$/'"'/
")"

这样,printf添加到 var 值的相同尾随换行符就是命令替换删除的换行符 - 这也是输出中的最后一个字符,因为倒数第二个字符始终是硬引号 - 并且安全地分隔了eval语句因为sed转义了可能出现在其输入中的任何硬引号,并且字符串的开头有一个。

但事实上,使用这样的命令替换通常并不是一个好的做法 - 也许这就是为什么它并不总是很合适的原因。通常,收集进程的每个进程循环的所有输出并将其在单个流上立即传递到管道中的另一个过滤器进程比以这种方式对过滤器进行精打细算更有效。

除非你的 shell 变量中有很大的值 - 这通常也是一个坏主意 - 像这样的东西可能是更好的方法:

set -- "$lol" 
while case "$1" in (*Dot*)
set -- "${1%Dot*}" "${1##*Dot}Dot
$2";;(*) ! lol=$1$2;; esac
do :; done

答案4

您可以将换行符\n与回车符一起使用\r。我sed手头没有 BSD来测试,但它可以与 GNU 一起使用sed

$ var=Dot
$ lol=$(echo $var | sed 's/Dot/Dot\n\r/g')
$ echo "$lol"
Dot

$

如果 BSDsed不支持,\r那么另一个(相当丑陋的)解决方案是使用\n\rorecho -e打印printf

lol=$(echo $var | sed "s/Dot/Dot\\$(printf '\n\r')/g")

相关内容