Основи на користење на уредувачот Sed Stream за манипулирање со текст во Linux


Вовед

Командата sed, кратенка за уредувач на пренос, врши операции за уредување на текст што доаѓа од стандарден влез или датотека. sed уредува ред по ред и на неинтеактивен начин.

Ова значи дека ги донесувате сите одлуки за уредување додека ја повикувате командата, а sed автоматски ги извршува насоките. Ова може да изгледа збунувачки или неинтуитивно, но тоа е многу моќен и брз начин за трансформирање на текстот, особено како дел од скрипта или автоматизиран работен тек.

Овој туторијал ќе опфати некои основни операции и ќе ве запознае со синтаксата потребна за ракување со овој уредувач. Речиси сигурно никогаш нема да го замените вашиот редовен уредувач на текст со sed, но тој веројатно ќе стане добредојден додаток во алатникот за уредување текст.

Забелешка: ова упатство ја користи GNU верзијата на sed што се наоѓа на Ubuntu и другите оперативни системи Linux. Ако користите macOS, ќе ја имате верзијата BSD која има различни опции и аргументи. Можете да ја инсталирате GNU верзијата на sed со Homebrew користејќи brew install gnu-sed.

Основна употреба

sed работи на тек на текст што го чита или од текстуална датотека или од стандарден влез (STDIN). Ова значи дека можете да испратите излез од друга команда директно во sed за уредување, или можете да работите на датотека што веќе сте ја создале.

Треба да знаете и дека sed стандардно излегува сè на стандардно (STDOUT). Тоа значи дека, освен ако не е пренасочено, sed ќе го отпечати својот излез на екранот наместо да го зачува во датотека.

Основната употреба е:

  1. sed [options] commands [file-to-edit]

Во ова упатство, ќе користите копија од лиценцата за софтвер BSD за да експериментирате со sed. На Ubuntu, извршете ги следните команди за да ја копирате датотеката со лиценца BSD во вашиот домашен директориум за да можете да работите со неа:

  1. cd
  2. cp /usr/share/common-licenses/BSD .

Ако немате локална копија на BSD лиценцата, креирајте ја сами со оваа команда:

  1. cat << 'EOF' > BSD
  2. Copyright (c) The Regents of the University of California.
  3. All rights reserved.
  4. Redistribution and use in source and binary forms, with or without
  5. modification, are permitted provided that the following conditions
  6. are met:
  7. 1. Redistributions of source code must retain the above copyright
  8. notice, this list of conditions and the following disclaimer.
  9. 2. Redistributions in binary form must reproduce the above copyright
  10. notice, this list of conditions and the following disclaimer in the
  11. documentation and/or other materials provided with the distribution.
  12. 3. Neither the name of the University nor the names of its contributors
  13. may be used to endorse or promote products derived from this software
  14. without specific prior written permission.
  15. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  16. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17. IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  18. ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  19. FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  20. DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  21. OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  22. HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  23. LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  24. OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  25. SUCH DAMAGE.
  26. EOF

Ајде да користиме sed за да ја прегледаме содржината на датотеката за лиценца BSD. sed стандардно ги испраќа своите резултати на екранот, што значи дека можете да го користите како читач на датотеки со тоа што не му давате наредби за уредување. Обидете се да ја извршите следнава команда:

  1. sed '' BSD

Ќе ја видите BSD лиценцата прикажана на екранот:

Output
Copyright (c) The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. ... ...

Единечните наводници ги содржат командите за уредување што ги предавате на sed. Во овој случај, ништо не сте го пренеле, па sed ја испечатил секоја линија што ја примил на стандарден излез.

sed може да користи стандарден влез наместо датотека. Ставете го излезот од командата cat во sed за да го добиете истиот резултат:

  1. cat BSD | sed ''

Ќе го видите излезот од датотеката:

Output
Copyright (c) The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. . . . . . .

Како што можете да видите, можете исто толку лесно да работите со датотеки или текови на текст, како оние што се создаваат при излегување на цевки со знакот на цевката (|).

Линии за печатење

Во претходниот пример, видовте дека влезот пренесен во sed без никакви операции ќе ги испечати резултатите директно на стандардниот излез.

Ајде да ја истражиме експлицитната команда print на sed, која ја одредувате со користење на знакот p во единечни наводници.

Извршете ја следнава команда:

  1. sed 'p' BSD

Ќе ја видите секоја линија од датотеката BSD испечатена двапати:

Output
Copyright (c) The Regents of the University of California. Copyright (c) The Regents of the University of California. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions modification, are permitted provided that the following conditions are met: are met: . . . . . .

sed автоматски ја печати секоја линија стандардно, а потоа сте му кажале да печати линии експлицитно со командата \p, така што секоја линија ќе се испечати двапати.

Ако внимателно го испитате излезот, ќе видите дека тој ја има првата линија двапати, проследена со втората линија двапати, итн, што ви кажува дека sed работи на податоци линија по линија. Чита линија, работи на неа и го издава добиениот текст пред да го повтори процесот на следниот ред.

Можете да ги исчистите резултатите со предавање на опцијата -n на sed, што го потиснува автоматското печатење:

  1. sed -n 'p' BSD
Output
Copyright (c) The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. . . . . . .

Сега се враќаме на печатење на секоја линија еднаш.

Досегашните примери тешко може да се сметаат за уредување (освен ако не сакате да го испечатите секој ред двапати…). Следно, ќе истражите како sed може да го измени излезот со таргетирање одредени делови од текстуалните податоци.

Користење на опсегот на адреси

Адресите ви дозволуваат да насочите одредени делови од текстуален тек. Можете да наведете одредена линија или дури и опсег на линии.

Ајде да го sed отпечатиме првиот ред од датотеката. Извршете ја следнава команда:

  1. sed -n '1p' BSD

Првата линија се печати на екранот:

Output
Copyright (c) The Regents of the University of California.

Со ставање на бројот 1 пред командата за печатење, му кажавте на sed бројот на линијата за работа. Можете исто толку лесно да испечатите пет линии (не заборавајте \-n):

  1. sed -n '1,5p' BSD

Ќе го видите овој излез:

Output
Copyright (c) The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions

Штотуку дадовте опсег на адреси на sed. Ако му дадете адреса на sed, тој ќе ги извршува само командите што следат на тие линии. Во овој пример, му кажавте на sed да ги отпечати линиите 1 до линијата 5. Можевте да го наведете ова на поинаков начин со давање на првата адреса, а потоа користејќи поместување за да му кажете на Сед колку дополнителни линии треба да патува, вака:

  1. sed -n '1,+4p' BSD

Ова ќе резултира со истиот излез, бидејќи му рековте на sed да започне од линијата 1 и потоа да работи и на следните 4 линии.

Ако сакате да ја испечатите секоја друга линија, наведете го интервалот по знакот ~. Следната команда ја печати секоја друга линија во датотеката BSD, почнувајќи од линијата 1:

  1. sed -n '1~2p' BSD

Еве го излезот што ќе го видите:

Output
Copyright (c) The Regents of the University of California. modification, are permitted provided that the following conditions 1. Redistributions of source code must retain the above copyright 2. Redistributions in binary form must reproduce the above copyright documentation and/or other materials provided with the distribution. may be used to endorse or promote products derived from this software . . . . . .

Можете да користите sed за да избришете текст и од излезот.

Бришење текст

Можете да извршите бришење текст онаму каде што претходно сте специфицирале печатење текст со менување на командата p во командата d.

Во овој случај, повеќе не ви треба командата -n бидејќи sed ќе отпечати се што не е избришано. Ова ќе ви помогне да видите што се случува.

Изменете ја последната команда од претходниот дел за да ја направите

  1. sed '1~2d' BSD

Резултатот е дека ја гледате секоја линија што не ви била дадена минатиот пат:

Output
All rights reserved. Redistribution and use in source and binary forms, with or without are met: notice, this list of conditions and the following disclaimer. notice, this list of conditions and the following disclaimer in the 3. Neither the name of the University nor the names of its contributors without specific prior written permission. . . . . . .

Важно е да се забележи дека нашата изворна датотека не е засегната. Сè уште е недопрена. Уредувањата се емитуваат на нашиот екран.

Ако сакаме да ги зачуваме нашите уредувања, можеме да го пренасочиме стандардниот излез во датотека како вака:

  1. sed '1~2d' BSD > everyother.txt

Сега отворете ја датотеката со cat:

  1. cat everyother.txt

Го гледате истиот излез што го видовте на екранот претходно:

Output
All rights reserved. Redistribution and use in source and binary forms, with or without are met: notice, this list of conditions and the following disclaimer. notice, this list of conditions and the following disclaimer in the 3. Neither the name of the University nor the names of its contributors without specific prior written permission. . . . . . .

Командата sed стандардно не ја уредува изворната датотека, но може да го промените ова однесување со додавање на опцијата -i, што значи „изврши уредувања на место“. Ова ќе ја промени изворната датотека.

Предупредување: Користењето на прекинувачот -i ќе ја презапише оригиналната датотека, па затоа треба да го користите ова внимателно. Прво извршете ги операциите без прекинувачот -i и потоа извршете ја командата повторно со -i откако ќе го добиете она што го сакате, ќе создадете резервна копија од оригиналната датотека или ќе ја пренасочите излез во датотека. Многу е лесно случајно да ја смените оригиналната датотека со прекинувачот -i.

Ајде да го пробаме со уредување на датотеката everyother.txt што штотуку ја создадовте, на место. Ајде дополнително да ја намалиме датотеката со бришење на секоја друга линија

  1. sed -i '1~2d' everyother.txt

Ако користите cat за прикажување на датотеката со cat everyother.txt, ќе видите дека датотеката е уредена.

Опцијата -i може да биде опасна. За среќа, sed ви дава можност да креирате резервна датотека пред уредувањето.

За да креирате резервна датотека пред уредувањето, додајте ја наставката за резервна копија директно по опцијата \-i:

  1. sed -i.bak '1~2d' everyother.txt

Ова создава резервна датотека со наставката .bak, а потоа ја уредува оригиналната датотека на место.

Следно, ќе погледнете како да користите sed за да извршите операции за пребарување и замена.

Замена на текст

Можеби најпознатата употреба за sed е замена на текст. sed може да бара текстуални обрасци користејќи регуларни изрази, а потоа пронајдениот текст да го замени со нешто друго.

Можете да дознаете повеќе за регуларните изрази со следење на Употреба на редовни изрази на Grep за пребарување на обрасци на текст во Linux.

Во својата најосновна форма, можете да менувате еден збор во друг збор користејќи ја следнава синтакса:

's/old_word/new_word/'

s е командата за замена. Трите коси црти (/) се користат за раздвојување на различните текстуални полиња. Може да користите други знаци за да ги разграничите полињата ако е покорисно.

На пример, ако се обидувате да промените име на веб-локација, користењето на друг разграниувач би било корисно бидејќи URL-адресите содржат коса црти.

Извршете ја следнава команда за да испечатите URL со echo и изменете ја со sed, користејќи го знакот долна црта (_) како разграничувач:

  1. echo "http://www.example.com/index.html" | sed 's_com/index_org/home_'

Ова го заменува com/index со org/home. Излезот ја прикажува изменетата URL адреса:

Output
http://www.example.org/home.html

Не заборавајте на конечниот разграниувач, или sed ќе се жали. Ако ја извршите оваа команда:

  1. echo "http://www.example.com/index.html" | sed 's_com/index_org/home'

Ќе го видите овој излез:

Output
sed: -e expression #1, char 20: unterminated `s' command

Ајде да создадеме нова датотека за да вежбаме некои замени. Извршете ја следнава команда за да креирате нова текстуална датотека наречена song.txt:

  1. echo "this is the song that never ends
  2. yes, it goes on and on, my friend
  3. some people started singing it
  4. not knowing what it was
  5. and they'll continue singing it forever
  6. just because..." > song.txt

Сега да го замениме изразот on со напред. Користете ја следнава команда:

  1. sed 's/on/forward/' song.txt

Излезот изгледа вака:

Output
this is the sforwardg that never ends yes, it goes forward and on, my friend some people started singing it not knowing what it was and they'll cforwardtinue singing it forever just because...

Овде можете да видите неколку значајни работи. Прво, е тоа што sed ги замени обрасците, а не зборовите. вклучено во песна се менува во препрати.

Другото нешто што треба да се забележи е дека на линијата 2, вториот on не беше променет во forward.

Ова е затоа што стандардно, командата s работи на првото совпаѓање во линијата, а потоа се префрла на следната линија. За да направите sed да го замени секој примерок на on наместо само првиот на секоја линија, мора да пренесете опционално знаменце на командата за замена.

Обезбедете го знамето g на командата за замена со тоа што ќе го ставите по множеството за замена:

  1. sed 's/on/forward/g' song.txt

Ќе го видите овој излез:

Output
this is the sforwardg that never ends yes, it goes forward and forward, my friend some people started singing it not knowing what it was and they'll cforwardtinue singing it forever just because...

Сега командата за замена го менува секој примерок.

Ако само сакавте да го промените вториот примерок на \on што sed го наоѓа на секоја линија, тогаш би го користеле бројот 2 наместо g:

  1. sed 's/on/forward/2' song.txt

Овој пат другите линии се непроменети, бидејќи немаат втора појава:

Output
this is the song that never ends yes, it goes on and forward, my friend some people started singing it not knowing what it was and they'll continue singing it forever just because...

Ако сакате само да видите кои линии се заменети, користете ја опцијата -n повторно за да го спречите автоматското печатење.

Потоа можете да ја предадете опцијата p на командата за замена за да ги испечатите линиите каде што се случила замената.

  1. sed -n 's/on/forward/2p' song.txt

Линијата што ја смени отпечатоците на екранот:

Output
yes, it goes on and forward, my friend

Како што можете да видите, можете да ги комбинирате знаменцата на крајот од командата.

Ако сакате процесот на пребарување да ги игнорира буквите, можете да го пренесете со знамето \i.

  1. sed 's/SINGING/saying/i' song.txt

Еве го излезот што ќе го видите:

Output
this is the song that never ends yes, it goes on and on, my friend some people started saying it not knowing what it was and they'll continue saying it forever just because...

Замена и упатување на соодветниот текст

Ако сакате да најдете посложени обрасци со правилни изрази, имате голем број различни методи за упатување на соодветниот шаблон во текстот за замена.

На пример, за да се совпадне од почетокот на линијата до at, користете ја следнава команда:

  1. sed 's/^.*at/REPLACED/' song.txt

Ќе го видите овој излез:

Output
REPLACED never ends yes, it goes on and on, my friend some people started singing it REPLACED it was and they'll continue singing it forever just because...

Може да видите дека изразот на џокер се совпаѓа од почетокот на линијата до последниот примерок на at.

Бидејќи не ја знаете точната фраза што ќе се совпадне во низата за пребарување, можете да го користите знакот & за да го претставите соодветниот текст во замената низа.

Да ставиме загради околу соодветниот текст:

  1. sed 's/^.*at/(&)/' song.txt

Ќе го видите овој излез:

Output
(this is the song that) never ends yes, it goes on and on, my friend some people started singing it (not knowing what) it was and they'll continue singing it forever just because...

Пофлексибилен начин за референцирање на совпаднат текст е да се користат загради за да се групираат делови од совпаднат текст.

Секоја група на текст за пребарување означена со загради може да се референцира со избеган референтен број. На пример, првата група загради може да се референцира со \1, втората со \2 и така натаму.

Во овој пример, ќе ги смениме првите два збора од секоја линија:

  1. sed 's/\([a-zA-Z0-9][a-zA-Z0-9]*\) \([a-zA-Z0-9][a-zA-Z0-9]*\)/\2 \1/' song.txt

Ќе го видите овој излез:

Output
is this the song that never ends yes, goes it on and on, my friend people some started singing it knowing not what it was they and'll continue singing it forever because just...

Како што можете да видите, резултатите не се совршени. На пример, втората линија го прескокнува првиот збор бидејќи има знак што не е наведен во нашиот сет на знаци. Слично на тоа, го третираше theyll како два збора во петтиот ред.

Ајде да го подобриме регуларниот израз за да бидеме попрецизни:

  1. sed 's/\([^ ][^ ]*\) \([^ ][^ ]*\)/\2 \1/' song.txt

Ќе го видите овој излез:

Output
is this the song that never ends it yes, goes on and on, my friend people some started singing it knowing not what it was they'll and continue singing it forever because... just

Ова е многу подобро од минатиот пат. Ова ги групира интерпункциските знаци со поврзаниот збор.

Забележете како го повторуваме изразот во заградите (еднаш без знакот *, а потоа еднаш со него). Ова е затоа што знакот * се совпаѓа со множеството знаци што доаѓа пред него нула или повеќе пати. Ова значи дека совпаѓањето со џокерот ќе се смета за \совпаѓање\ дури и ако шемата не е пронајдена.

За да се осигурате дека sed го наоѓа текстот барем еднаш, мора да го совпаднете еднаш без џокерот пред да ја употребите џокерот.

Заклучок

Во ова упатство ја истражувавте командата sed. Испечативте одредени линии од датотеката, баравте текст, избришавте линии, ја пребришавте оригиналната датотека и користевте регуларни изрази за да го замените текстот. Веќе треба да можете да видите како можете брзо да трансформирате текстуален документ користејќи правилно конструирани sed команди.

Во следната статија од оваа серија, ќе истражите некои понапредни функции.