sed替换变量包含换行符(保留它)

时间:2015-02-22 23:38:32

标签: sed

我有一个多行字符串,从网上下载:

toast the lemonade
blend with the lemonade
add one tablespoon of the lemonade
grill the spring onions
add the lemonade
add the raisins to the saucepan
rinse the horseradish sauce

我已将此分配给$INPUT,如下所示:

INPUT=$(lynx --dump 'http://example.net/recipes' \
     | python -m json.tool \
     | awk '/steps/,/]/' \
     | egrep -v "steps|]" \
     | sed 's/[",]\|^ *//g; $d')

此时,$INPUT已准备好替换到我的目标文件中,如下所示:

sed -i "0,/OLDINPUT/s//$INPUT/" /home/test_file

当然,sed抱怨未命令的s命令 - 这就是问题所在。

我使用的当前解决方法是在将其提供给sed之前echo $INPUT,但之后不会保留换行符。 echo删除换行符 - 这就是问题所在。

正确的输出应保持其换行符。如何指示sed保留换行符?

5 个答案:

答案 0 :(得分:3)

hacky直接回答是用\n替换所有换行符,您可以通过添加

来替换
| sed ':a $!{N; ba}; s/\n/\\n/g'

到上面的长命令。一个更好的答案,因为将shell变量替换为代码总是一个坏主意,而且你不能选择sed,而是使用awk:

awk -i inplace -v input="$INPUT" 'NR == 1, /OLDINPUT/ { sub(/OLDINPUT/, input) } 1' /home/test_file

这需要-i inplace的GNU awk 4.1.0或更高版本。

答案 1 :(得分:2)

要清理一些代码。

此:

lynx --dump 'http://somesite.net/recipes' | python -m json.tool | awk '/steps/,/]/' | egrep -v "steps|]" | sed 's/"//g' |sed 's/,//g' | sed 's/^ *//g' | sed '$d'

可以替换为:

lynx --dump 'http://somesite.net/recipes' | python -m json.tool | awk '/]/ {f=0} f {if (c--) print line} /steps/{f=1} {gsub(/[",]|^ */,"");line=$0}'

它可能会缩短更多,但我现在不会这样做:python -m json.tool

此:

awk '/]/ {f=0} f {if (c--) print line} /steps/{f=1} {gsub(/[",]|^ */,"");line=$0}'

的作用:

  1. 将图案steps后面的行打印到]之前的行 - awk '/steps/,/]/' | egrep -v "steps|]"
  2. 删除",以及所有行前面的所有空格。 - sed 's/"//g' |sed 's/,//g' | sed 's/^ *//g'
  3. 然后删除该组的最后一行。 - sed '$d'

  4. 示例:

    cat file
    my data
    steps data
     more
     do not delet this
    hei "you" , more data
    extra line
    here is end ]
    this is good
    

    awk '/]/ {f=0} f {if (c--) print line} /steps/{f=1} {gsub(/[",]|^ */,"");line=$0}' file
    more
    do not delet this
    hei you  more data
    

答案 2 :(得分:2)

您希望使用编辑器代替sed的替换:

$ input="toast the lemonade
blend with the lemonade
add one tablespoon of the lemonade
grill the spring onions
add the lemonade
add the raisins to the saucepan
rinse the horseradish sauce"

$ seq 10 > file

$ ed file <<END
1,/5/d
1i
$input
.
w
q
END

$ cat file
toast the lemonade
blend with the lemonade
add one tablespoon of the lemonade
grill the spring onions
add the lemonade
add the raisins to the saucepan
rinse the horseradish sauce
6
7
8
9
10

答案 3 :(得分:2)

假设您输入的JSON片段如下所示:

{ "other": "random stuff",
  "steps": [
    "toast the lemonade",
    "blend with the lemonade",
    "add one tablespoon of the lemonade",
    "grill the spring onions",
    "add the lemonade",
    "add the raisins to the saucepan",
    "rinse the horseradish sauce"
  ],
  "still": "yet more stuff" }

您只能使用

提取steps成员
jq -r .steps

要将其插入到sed语句中,您需要在结果中转义任何正则表达式元字符。一个不那么令人生畏和希望稍微不那么讨厌的解决方案就是从标准输入中读取静态文本:

lynx ... | jq ... |
sed -i -e '/OLDINPUT/{s///; r /dev/stdin' -e '}' /home/test_file

教育从业者使用结构感知工具进行结构化数据的斗争已达到epic的高度并且一直没有减弱。在您决定使用快速和肮脏的方法之前,至少要确保您了解危险(技术和心理)。

答案 4 :(得分:2)

如果您正在使用Bash,则可以将\n替换为换行符:

INPUT="${INPUT//
/\\n}"

如果您不喜欢参数扩展中的文字换行,您可能更喜欢

INPUT="${INPUT//$'\n'/\\n}"

旁注 - 你可能意味着c将匹配的行改为输入,而不是s ubstitute。在这种情况下,毕竟你不想引用新行...