Bash:在初始注释后将行插入源代码文件

Bash:在初始注释后将行插入源代码文件,bash,shell,Bash,Shell,我需要使用bash在python文件中插入一行。该行需要出现在文件中任何初始注释之后 因此,考虑到文件: #!/usr/bin/python # This is just # an example comment moo = "cow" ... etc ... 我需要一个bash命令来插入新行,如下所示: #!/usr/bin/python # This is just # an example comment NEW LINE GOES HERE moo = "cow" ... et

我需要使用bash在python文件中插入一行。该行需要出现在文件中任何初始注释之后

因此,考虑到文件:

#!/usr/bin/python
# This is just 
# an example comment

moo = "cow"
... etc ...
我需要一个bash命令来插入新行,如下所示:

#!/usr/bin/python
# This is just 
# an example comment
NEW LINE GOES HERE

moo = "cow"
... etc ...
我完全不知道该怎么做。我试着一行一行地在文件上循环,但结果是非常可怕的,并且严重地弄乱了文件的空白

任何建议都很好

亚当

是的,这有点奇怪,它是持续集成构建脚本的一部分


编辑

记录在案,我尝试的代码是:

insert_setup_code() {
    installed=false
    tmpfile="/tmp/$RANDOM"

    cat "$INSTALL_TO" | while read -d \n l; do
        echo "$l" >> $tmpfile
        if [[ ! $installed && ! `echo "$l" | grep "^#"` ]]; then
            echo "LINE OF CODE HERE" >> $tmpfile
            installed=true
        fi
    done
}

您可以将存根、新行和剩余内容作为变量添加到bash脚本中,即

HEADER="!#/usr/bin/bla bla.."

YOUR_LINE="NEW LINE GOES HERE"

REST="more stuff"
并将它们导入到新脚本中

echo "$HEADER" "$YOUR_LINE" "$REST" > pytonscript.py
假设
YOUR_LINE
变量是动态的,但是如果
HEADER
REST
是静态的,应该可以工作,如果它们也是动态的,那么您可以使用
head
tail
结合
wc-l
来计算应该包含哪些行

我的
addline
脚本。在
filein
中的任何初始注释后添加
newline
,并写入
fileout

根据您的需要进行调整:)


对其自身的示例用法:

$ bash addline "# a test comment line" addline foo
$ cat foo

#!/usr/bin/env bash
# a test comment line

newline="$1"
filein="$2"
fileout="$3"
added=0

while read -r; do
    if ! ((added)) && ! [[ $REPLY =~ ^# ]]; then
        printf "%s\n" "$newline" >> "$fileout"
        ((added++))
    fi
    printf "%s\n" "$REPLY" >> "$fileout"
done < "$filein"
如前所述

我会写:

line="NEW STUFF HERE"
awk -v text="$line" '!/^#/ && !p {print text; p=1} 1' file
第一个非注释行将触发块打印该行:

  • /^#/--行不以哈希开头
  • !p
    --变量p不是真的

仅供参考,您的bash版本会是这样的

insert_setup_code() {
        install_to="$1"
        tmp=$(mktemp -t setup)

        added=0
        while IFS=$'\n' read -r line ; do
                printf "$line\n" >> "$tmp"
                [ $added = 0 ] && grep -q '^#' <<<"$line" && printf "LINE OF CODE HERE\n" >>"$tmp" && added=1
        done < "$install_to"

        mv -f "$tmp" "$install_to"
}
插入\u设置\u代码(){
将_安装到=“$1”
tmp=$(mktemp-t设置)
已添加=0
而IFS=$'\n'读取-r行;执行
printf“$line\n”>>“$tmp”

[$added=0]&&grep-q'^#'找到第一个空行

$ grep -n -m1 '^$' input | cut -d: -f1 
4
使用该行号并将其更改为其他字符串,
-i
以在位编辑文件(小心使用!)

另一种方法是对不包含
#
的第一行进行grep,然后上述内容变为:

$ grep -n -m1 '^[^#]' input | cut -d: -f1
5

$ sed -i "5i NEW STUFF HERE" input

$ cat input
#!/usr/bin/python
# This is just 
# an example comment

NEW STUFF HERE
moo = "cow"
... etc ...
要在sed脚本中使用shell变量,请使用此方法,其中
允许展开变量

sed "${num}c NEW STUFF HERE" log

使用
ed
无需tmp文件

以下代码假定在第一个非空行(不以
字符开头)之前,只有空行或以
字符开头的行

# insert a line just before the first line that does not begin with a '#' char
# skips empty lines and lines containing whitespace characters only
# for more information on ed see http://wiki.bash-hackers.org/howto/edit-ed

cat <<-'EOF' | ed -s file
H
/^[[:space:]]*[^#[:space:]]/i
NEW STUFF HERE
.
wq
EOF
#在第一行前面插入一行,该行不以“#”字符开头
#跳过空行和仅包含空格字符的行
#有关ed的更多信息,请参阅http://wiki.bash-hackers.org/howto/edit-ed

cat这是因为你没有使用足够的引号。嗨,Ignacio,你能详细说明一下吗?我已经发布了我在上面尝试的代码。谢谢!你应该使用
mktemp
创建一个新的临时文件。也不要忘了在完成后删除它。请注意,
mktemp
是不可移植的,这不是POSIX指定的。很好!但是,它仍然看起来很好从行的开头和开始处去掉空格。你知道如何避免吗?仅供参考,在读取时不丢失空格的诀窍是更改IFS,例如:
,而IFS=$'\n'read-r whatever;Do…等
,请参阅我的答案以获得一个工作示例。直观的答案是
read-d'\n'
,但这与用户的类型不同Illy期望,而设置IFS则会。有很多方法可以避免丢失空白。要么像我一样使用
REPLY
变量,要么像你一样将
IFS=
设置为nothing,要么像你一样将其设置为
\n
。所有方法都有效。嘿,比亚尼。这是我最初的计划,但我实际上不知道注释会持续多长时间,或者一次是否会有注释我有一个主意,我会在我的回答中发出来的。我想你似乎从@c00kiemons5ter这里得到了一个更深思熟虑的答案,所以我猜它已经启动并运行了:)+1一行:D gah,awk就可以了。我有空的时候应该研究一下:)这很明显Glenn会想出一个完美且最优雅的解决方案。我本可以预测到。我只是在等待一个比我更在行的人来添加相应的
sed
版本。(-:
$ sed -i '4c NEW STUFF HERE' input

$ cat input
#!/usr/bin/python
# This is just 
# an example comment
NEW STUFF HERE
moo = "cow"
... etc ...
$ grep -n -m1 '^[^#]' input | cut -d: -f1
5

$ sed -i "5i NEW STUFF HERE" input

$ cat input
#!/usr/bin/python
# This is just 
# an example comment

NEW STUFF HERE
moo = "cow"
... etc ...
sed "${num}c NEW STUFF HERE" log
# insert a line just before the first line that does not begin with a '#' char
# skips empty lines and lines containing whitespace characters only
# for more information on ed see http://wiki.bash-hackers.org/howto/edit-ed

cat <<-'EOF' | ed -s file
H
/^[[:space:]]*[^#[:space:]]/i
NEW STUFF HERE
.
wq
EOF
# using FreeBSD ed (on Mac OS X)
cat <<-'EOF' | ed -s file
H
,v/^#/u\
u\
i\
NEW STUFF HERE\
.
wq
EOF


# using sed & ed
# first get the line number of the first line not beginning with a '#' char;
# then use ed for in-place file editing
lno=$(sed -n '/^#/!{=;q;}' file) &&
cat <<-EOF | ed -s file
H
${lno},${lno}i
NEW STUFF HERE
.
wq
EOF