Вставте рядок під певним номером рядка з sed або awk


146

У мене є файл сценарію, який мені потрібно змінити іншим сценарієм, щоб вставити текст у 8-му рядку.

Рядок для вставки: Project_Name=sowstestу файл, який називається start.

Я намагався використовувати awk і sed, але моя команда стає ошелешеною.

Відповіді:


231
sed -i '8i8 This is Line 8' FILE

вставки по лінії 8

8 This is Line 8

у файл FILE

-i робить модифікацію безпосередньо для файлу FILE, виводу до stdout немає, як згадується у коментарях glenn jackman.


3
Так, перемикач -i є специфічним для GNU-sed.
користувач невідомий

1
Ні. -I означає "змінити вказаний файл на місці". Вставка проти додавання досягається за допомогою "8isomething" проти "8asomething", незалежно від перемикача -i.
користувач невідомий

11
користувачі mac: з домашньою мовою, brew install gnu-sedа потім скористайтеся цимgsed
cwd

4
Це супер корисно! Чи все-таки мені потрібно вставити пробіли на початку рядка? Я помітив, що sed не звертає уваги на початковий пробіл ...
elju

9
@elju: Так, замаскувати його за допомогою зворотного косою риси: sed '8i\ 8 This is Line 8' FILE.
користувач невідомий

32

edвідповідь

ed file << END
8i
Project_Name=sowstest
.
w
q
END

.у власному рядку закінчується режим введення; wпише; qкидає. У GNU ed є wqкоманда зберігати та виходити, але стара редакція цього не робить.

Подальше читання: https://gnu.org/software/ed/manual/ed_manual.html


19

OS X / macOS / FreeBSD sed

-iПрапор працює по- різному на MacOS , sedніж в GNU sed.

Ось спосіб використовувати його в macOS / OS X:

sed -i '' '8i\
8 This is Line 8' FILE

Див. Для man 1 sedотримання додаткової інформації.


18

відповідь awk

awk -v n=8 -v s="Project_Name=sowstest" 'NR == n {print s} {print}' file > file.new

@glenn jackman Мені потрібно перейти #define SERVER@"http://10.35.42.54/ms0.8"до певного рядка. Як я можу цього досягти?
Невін Радж Віктор

1
Я думаю, що Невіну просто потрібно уникати цитат у його рядку із зворотними
косими рисами

@waLLe, почніть з інформаційної сторінки awk, яка містить хороший опис того, як працює awk. Тут у мене є 2 пари "умова {дія}", у другої немає умови, що означає, що дія виконується для кожного запису. Після того, як ви закінчите читати і у вас ще залишаються питання, дайте мені знати.
Гленн Джекман

@glennjackman майже там .. просто цього не дійшло: файл> file.new
w411 3

"файл" позначає ім'я файлу, над яким працює awk. >є символом перенаправлення оболонки, щоб висновок awk зберігався у файлі під назвою "file.new".
glenn jackman

16

POSIX sed(і, наприклад, OS X sed, sedнижче), iповинен супроводжуватися зворотним нахилом та новою лінією. Також принаймні ОС X sedне включає новий рядок після вставленого тексту:

$ seq 3|gsed '2i1.5'
1
1.5
2
3
$ seq 3|sed '2i1.5'
sed: 1: "2i1.5": command i expects \ followed by text
$ seq 3|sed $'2i\\\n1.5'
1
1.52
3
$ seq 3|sed $'2i\\\n1.5\n'
1
1.5
2
3

Щоб замінити рядок, ви можете використовувати команди c(зміни) або s(замінити) з числовою адресою:

$ seq 3|sed $'2c\\\n1.5\n'
1
1.5
3
$ seq 3|gsed '2c1.5'
1
1.5
3
$ seq 3|sed '2s/.*/1.5/'
1
1.5
3

Альтернативи з використанням awk:

$ seq 3|awk 'NR==2{print 1.5}1'
1
1.5
2
3
$ seq 3|awk '{print NR==2?1.5:$0}'
1
1.5
3

awkінтерпретує зворотні риски змінних змінних, переданих, -vале не змінних, переданих за допомогою ENVIRON:

$ seq 3|awk -v v='a\ba' '{print NR==2?v:$0}'
1
a
3
$ seq 3|v='a\ba' awk '{print NR==2?ENVIRON["v"]:$0}'
1
a\ba
3

Обидва ENVIRONі -vвизначаються POSIX.


7

Рішення Perl:

швидко і брудно:

perl -lpe 'print "Project_Name=sowstest" if $. == 8' file

  • -l знімає нові рядки та додає їх назад, усуваючи необхідність "\ n"
  • -p петлі над вхідним файлом, друкуючи кожен рядок
  • -e виконує код в одиничних лапках

$. номер рядка

еквівалентний awk-рішенню @ glenn, використовуючи названі аргументи:

perl -slpe 'print $s if $. == $n' -- -n=8 -s="Project_Name=sowstest" file

  • -s вмикає аналізатор рудиментарних аргументів
  • -- запобігає розбору -n і -s стандартним аналізатором аргументів perl

позиційні аргументи команди:

perl -lpe 'BEGIN{$n=shift; $s=shift}; print $s if $. == $n' 8 "Project_Name=sowstest" file

змінні середовища:

setenv n 8 ; setenv s "Project_Name=sowstest"
echo $n ; echo $s
perl -slpe 'print $ENV{s} if $. == $ENV{n}' file

ENV це хеш, який містить усі змінні середовища

Getopt для аналізу аргументів на хеш% o:

perl -MGetopt::Std -lpe 'BEGIN{getopt("ns",\%o)}; print $o{s} if $. == $o{n}' -- -n 8 -s "Project_Name=sowstest" file

Getopt :: Довгі та довші назви опцій

perl -MGetopt::Long -lpe 'BEGIN{GetOptions(\%o,"line=i","string=s")}; print $o{string} if $. == $o{line}' -- --line 8 --string "Project_Name=sowstest" file

Getopt - рекомендоване стандартне бібліотечне рішення.
Це може бути зайвим для однорядних сценаріїв perl, але це можна зробити


2
Кудо, тобі Кріс за те, що ти знайшов час, щоб пояснити все це, і виклав це так гарно, але ось ось чому я не люблю перл.
rsaw

5

Для тих, хто перебуває на SunOS, який не є GNU, допоможе наступний код:

sed '1i\^J
line to add' test.dat > tmp.dat
  • ^ J вставляється з ^ V + ^ J
  • Додати новий рядок після '1i.
  • \ ОБОВ'ЯЗКОВО бути останнім символом рядка.
  • Друга частина команди повинна бути у другому рядку.

5

sed -e '8iProject_Name=sowstest' -i start з використанням GNU sed

Проба зразка:

[root@node23 ~]# for ((i=1; i<=10; i++)); do echo "Line #$i"; done > a_file
[root@node23 ~]# cat a_file
Line #1
Line #2
Line #3
Line #4
Line #5
Line #6
Line #7
Line #8
Line #9
Line #10
[root@node23 ~]# sed -e '3ixxx inserted line xxx' -i a_file 
[root@node23 ~]# cat -An a_file 
     1  Line #1$
     2  Line #2$
     3  xxx inserted line xxx$
     4  Line #3$
     5  Line #4$
     6  Line #5$
     7  Line #6$
     8  Line #7$
     9  Line #8$
    10  Line #9$
    11  Line #10$
[root@node23 ~]# 
[root@node23 ~]# sed -e '5ixxx (inserted) "line" xxx' -i a_file
[root@node23 ~]# cat -n a_file 
     1  Line #1
     2  Line #2
     3  xxx inserted line xxx
     4  Line #3
     5  xxx (inserted) "line" xxx
     6  Line #4
     7  Line #5
     8  Line #6
     9  Line #7
    10  Line #8
    11  Line #9
    12  Line #10
[root@node23 ~]# 

Звідки проходить кінцева $лінія з лінії 3 після вставки?
jww

Це від -Aпрапора до cat:)
jno

що робити, якщо рядок, яку ви хочете вставити, містить лапки, дужки тощо?
Анентропний

Дивіться оновлення до тексту вище. Це означає, що вам доведеться уникнути цих ознак, як це доречно.
Jno

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.