Bash 在第一个空行之前插入变量中分配的文本

Bash 在第一个空行之前插入变量中分配的文本,bash,sed,Bash,Sed,我有一些类似于以下内容的文本文件 function %blah %blah %blah code here 我想在第一个空行之前附加以下文本: % %This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike %3.0 Unported License. See notes at the end of this file for more information. 我尝试了以下

我有一些类似于以下内容的文本文件

function
%blah
%blah

%blah
code here
我想在第一个空行之前附加以下文本:

%
%This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 
%3.0 Unported License. See notes at the end of this file for more information.
我尝试了以下方法:

top=$(cat ./PATH/text.txt) 
top="${top//$'\n'/\\n}" 
sed -i.bak 's@^$@'"$top"'\\n@' $f
其中第二行(我认为)保留文本中的新行,第三行(我认为)用文本加上新的空行替换第一个空行

两个问题:

1-我的代码附加以下文本:

%n%本作品根据知识共享协议获得许可 属性非商业性ShareSameline n%3.0未导入的许可证。见附注 有关详细信息,请参阅此文件末尾。\n

2-它将其附加到文件的末尾


有人能帮我理解代码的问题吗?

如果您使用的是
GNU-sed
,下面的方法就行了

使用
^$
查找空行,然后使用
sed
替换/放置所需的文本

# Define your replacement text in a variable
a="%\n%This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike\n%3.0 Unported License. See notes at the end of this file for more information."
注意,
$a
应包括那些将由
sed
直接解释为换行符的
\n

$ sed "0,/^$/s//$a/" inputfile.txt
在上述语法中,
0
表示第一次出现

输出:

function
%blah
%blah
%
%This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike
%3.0 Unported License. See notes at the end of this file for more information.
%blah
code here

test
您已在问题中包含和标记。由于我似乎无法在
sed
中找到实现这一点的方法,因此这里有一个仅适用于bash的解决方案。它可能会执行您可能找到的所有工作解决方案中最糟糕的一个

以下内容适用于您的示例输入:

$ while read -r x; do [[ -z "$x" ]] && cat boilerplate; printf '%s\n' "$x"; done < src
这个awk解决方案显然会将样板读入一个变量,尽管它不是一个shell变量

尽管有非标准的平台特定扩展,awk也没有任何“就地”编辑文件的功能。使用awk的便携式解决方案仍然需要推送临时文件


当然,下面的
ed
旧标准非常适合放在你的后口袋里:

printf 'H\n/^$/\n-\n.r boilerplate\nw\nq\n' | ed src
当然,在bash中,您可以始终使用heretext,这可能更清楚:

$ ed src <<< $'H\n/^$/\n-\n.r boilerplate\nw\nq\n'
或者您可以将ed脚本放入由printf构造的变量中

printf -v scr 'H\n/^$/\n-\n.r ./TATTOO_%s/top.txt\nw\nq\n' "$currn"

ed "$file" <<< "$scr"`
printf-v scr'H\n/^$/\n-\n.r./纹身\uuu%s/top.txt\nw\nq\n'“$currn”

ed“$file”将文本添加到变量中以便插入变量是浪费和不必要的复杂
sed
可以轻松地读取文件本身的内容

sed -i.bak '1r./PATH/text.txt' "$f"
不幸的是,
sed
的这一部分标准化程度很低,因此您可能需要进行一些实验。有些方言要求在文件名前加一个换行符(可能是,也可能不是,前面加一个反斜杠)

sed -i.bak '1r\
./PATH/text.txt' "$f"
(还请注意文件名周围的双引号。通常,在包含文件名的变量周围总是需要双引号。)

我们可以将其扩展为应用于第一个空行,而不是第一行

sed -i.bak -e '/^$/!b' -e 'r./PATH/text.txt' -e :a -e '$!{' -e n -e ba -e } "$f"
这会在第一个空行之后添加样板文件,但这可能是可以接受的。无论如何,重构它以替换它或在后面添加一个空行应该不会太有挑战性。(可以使用
sed-n
,而是显式打印除空行以外的所有内容。)


简而言之,这会一直跳到最后(简单地打印),直到找到第一个空行。然后,我们读取并打印文件,然后进入一个循环,该循环打印文件的其余部分,而不返回脚本的开头。

sed
,我认为这是可行的。使用文件作为要插入的额外位

b='##\n## comment piece\n##'

sed --posix -ne '
   1,/^$/ {
     /^$/ {
       x;
       /^true$/ !{
         x
         s/^$/true/
         i\
'"$b"'
        };
        x;
        s/^.*$//
      }
   }
p
' file1
对于使用范围为
1、/^$/
的示例,第一行为空将导致免责声明打印两次。为了避免这种情况,我将其设置为在保留空间(
x;s/^$/true/
)中放置一个标志,我可以将其切换到模式空间,以检查它是否为第一个空格。一旦有空行匹配,
i\
将注释(
$b
)插入到模式空间前面


感谢ghoti提供的初始计划。

为什么
sed
是您选择的工具?在替换字符串中转换为换行符的
\n
可能在sed的某些变体中起作用,但它远不是通用行为。此解决方案在FreeBSD或macOS中不起作用。我没有进一步测试。默认情况下,MacOS使用FreeBSD
sed
。它们不是两个独立的案例。编辑了我的回答,指出您可以在GNU sed中使用它。事实上,它们是两种独立的情况,因为它们是不同的操作系统。FreeBSD的sed确实不同于macOS中的sed,尽管它有一个共同的祖先。无论如何,谢谢你的澄清。如果无法创建可移植答案,请务必注意答案的限制。很好,这演示了如何读取文件,但是您如何使sed在文件的第一个空行之前插入文件<代码> '/^ $/R文件'/COD>将在空白行之后插入它。哦,还有,这是否使用GNUisms?添加了循环后,这在FreeBSD中对我根本不起作用。删除空行并在之后打印它应该是一个小的重构。据我所知,循环应该是可移植的,但我会看看是否能找到bug。谢谢你的反馈!不知道我们做的有什么不同。我在FreeBSD和macOS中得到了相同的行为-
sed-e'/^$/r file2'file1
在空行后插入file2,添加循环会使这变成一个非常复杂的
cat
:)虽然我不能解释后者,但前者对我来说是有意义的。你怎么认为你的
/^$/
条件只会匹配一次呢?我又对它进行了一些重构。我想我现在已经开始工作了,还有一些警告。再次感谢您的鼓励。这是我所得到的:
sed-ne'1,/^$/{p;/^$/{r file2'-e'};};/^$/,$p'文件1
。看来我们都被插入在空白之后而不是在SED之前发生了。和。。我的荣幸,这些都是有趣的练习。我试图找到一个很好的参考,说明为什么在阅读
处理文件时要避免
。我不能很快找到任何真正集中和权威的东西,但是试试@tripleee,谢谢
sed -i.bak '1r\
./PATH/text.txt' "$f"
sed -i.bak -e '/^$/!b' -e 'r./PATH/text.txt' -e :a -e '$!{' -e n -e ba -e } "$f"
b='##\n## comment piece\n##'

sed --posix -ne '
   1,/^$/ {
     /^$/ {
       x;
       /^true$/ !{
         x
         s/^$/true/
         i\
'"$b"'
        };
        x;
        s/^.*$//
      }
   }
p
' file1