Bash: вставить строку в файл исходного кода после начальных комментариев - PullRequest
2 голосов
/ 05 июля 2011

Мне нужно использовать 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 ...

Я совершенно туп, как это сделать.Я пытался циклически перебирать файл, но это просто ужасно и сильно портит пробел в файле.

Любые предложения будут великолепны!

Адам

PS.Да, это немного странно, это часть скрипта непрерывной интеграции.


Редактировать

Для записи:код, который я пробовал, был:

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
}

Ответы [ 6 ]

11 голосов
/ 05 июля 2011

Я бы написал:

line="NEW STUFF HERE"
awk -v text="$line" '!/^#/ && !p {print text; p=1} 1' file

Первая строка без комментариев приведет к тому, что блок напечатает строку:

  • !/^#/ - строка не начинается схеш
  • !p - переменная p неверна
1 голос
/ 05 июля 2011

вот, пожалуйста,

мой addline скрипт.добавить newline после любых начальных комментариев в filein и записать в fileout

#!/usr/bin/env bash

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"

Использовать как:

$ bash addline "my new line" "readThisFile" "writeToThisFile"

настроить в соответствии с вашими потребностями:)


пример использования для себя:

$ 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"

Обновлена ​​более быстрая версия:
с использованием wc -l и sed для записи оставшейся части файла вместо циклического прохождения каждой строки

#!/usr/bin/env bash

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

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

sed -n "$counter,$(wc -l < "$filein")p" "$filein" >> "$fileout"

работает как прежде / выше

0 голосов
/ 05 июля 2011

При использовании ed нет необходимости в файле tmp.

В следующем коде предполагается, что есть только пустые строки или строки, начинающиеся с символа # перед первой непустой строкой, которая выполняетне начинаться с # char.

# 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
0 голосов
/ 05 июля 2011

Найдите первую пустую строку

$ grep -n -m1 '^$' input | cut -d: -f1 
4

Используйте этот номер строки и измените его на другую строку, -i, чтобы редактировать файлы на месте (используйте с осторожностью!)

$ 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 для первой строки, которая не содержит #, тогда приведено выше:

$ 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-скрипте, используйте этот подход,где " позволяет расширять переменные

sed "${num}c NEW STUFF HERE" log
0 голосов
/ 05 июля 2011

К вашему сведению, ваша 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"
}

Но, конечно, необходимо предпринять дополнительные настройки, если вы хотите сохранить метаданные в файле $install_to

0 голосов
/ 05 июля 2011

вы можете добавить заглушку, новую строку и остальные данные в качестве переменных в сценарии 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 для расчета того, какие строки следует включить

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...