Основи на користење на уредувачот 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
ќе го отпечати својот излез на екранот наместо да го зачува во датотека.
Основната употреба е:
- sed [options] commands [file-to-edit]
Во ова упатство, ќе користите копија од лиценцата за софтвер BSD за да експериментирате со sed
. На Ubuntu, извршете ги следните команди за да ја копирате датотеката со лиценца BSD во вашиот домашен директориум за да можете да работите со неа:
- cd
- cp /usr/share/common-licenses/BSD .
Ако немате локална копија на BSD лиценцата, креирајте ја сами со оваа команда:
- cat << 'EOF' > BSD
- 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.
- 3. Neither the name of the University nor the names of its contributors
- may be used to endorse or promote products derived from this software
- without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- SUCH DAMAGE.
- EOF
Ајде да користиме sed
за да ја прегледаме содржината на датотеката за лиценца BSD. sed
стандардно ги испраќа своите резултати на екранот, што значи дека можете да го користите како читач на датотеки со тоа што не му давате наредби за уредување. Обидете се да ја извршите следнава команда:
- sed '' BSD
Ќе ја видите BSD лиценцата прикажана на екранот:
OutputCopyright (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
за да го добиете истиот резултат:
- cat BSD | sed ''
Ќе го видите излезот од датотеката:
OutputCopyright (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
во единечни наводници.
Извршете ја следнава команда:
- sed 'p' BSD
Ќе ја видите секоја линија од датотеката BSD
испечатена двапати:
OutputCopyright (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
, што го потиснува автоматското печатење:
- sed -n 'p' BSD
OutputCopyright (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 -n '1p' BSD
Првата линија се печати на екранот:
OutputCopyright (c) The Regents of the University of California.
Со ставање на бројот 1
пред командата за печатење, му кажавте на sed
бројот на линијата за работа. Можете исто толку лесно да испечатите пет линии (не заборавајте \-n):
- sed -n '1,5p' BSD
Ќе го видите овој излез:
OutputCopyright (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. Можевте да го наведете ова на поинаков начин со давање на првата адреса, а потоа користејќи поместување за да му кажете на Сед колку дополнителни линии треба да патува, вака:
- sed -n '1,+4p' BSD
Ова ќе резултира со истиот излез, бидејќи му рековте на sed
да започне од линијата 1 и потоа да работи и на следните 4 линии.
Ако сакате да ја испечатите секоја друга линија, наведете го интервалот по знакот ~
. Следната команда ја печати секоја друга линија во датотеката BSD
, почнувајќи од линијата 1:
- sed -n '1~2p' BSD
Еве го излезот што ќе го видите:
OutputCopyright (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
ќе отпечати се што не е избришано. Ова ќе ви помогне да видите што се случува.
Изменете ја последната команда од претходниот дел за да ја направите
- sed '1~2d' BSD
Резултатот е дека ја гледате секоја линија што не ви била дадена минатиот пат:
OutputAll 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 '1~2d' BSD > everyother.txt
Сега отворете ја датотеката со cat
:
- cat everyother.txt
Го гледате истиот излез што го видовте на екранот претходно:
OutputAll 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
што штотуку ја создадовте, на место. Ајде дополнително да ја намалиме датотеката со бришење на секоја друга линија
- sed -i '1~2d' everyother.txt
Ако користите cat
за прикажување на датотеката со cat everyother.txt
, ќе видите дека датотеката е уредена.
Опцијата -i
може да биде опасна. За среќа, sed
ви дава можност да креирате резервна датотека пред уредувањето.
За да креирате резервна датотека пред уредувањето, додајте ја наставката за резервна копија директно по опцијата \-i:
- sed -i.bak '1~2d' everyother.txt
Ова создава резервна датотека со наставката .bak
, а потоа ја уредува оригиналната датотека на место.
Следно, ќе погледнете како да користите sed
за да извршите операции за пребарување и замена.
Замена на текст
Можеби најпознатата употреба за sed
е замена на текст. sed
може да бара текстуални обрасци користејќи регуларни изрази, а потоа пронајдениот текст да го замени со нешто друго.
Можете да дознаете повеќе за регуларните изрази со следење на Употреба на редовни изрази на Grep за пребарување на обрасци на текст во Linux.
Во својата најосновна форма, можете да менувате еден збор во друг збор користејќи ја следнава синтакса:
's/old_word/new_word/'
s
е командата за замена. Трите коси црти (/
) се користат за раздвојување на различните текстуални полиња. Може да користите други знаци за да ги разграничите полињата ако е покорисно.
На пример, ако се обидувате да промените име на веб-локација, користењето на друг разграниувач би било корисно бидејќи URL-адресите содржат коса црти.
Извршете ја следнава команда за да испечатите URL со echo
и изменете ја со sed
, користејќи го знакот долна црта (_
) како разграничувач:
- echo "http://www.example.com/index.html" | sed 's_com/index_org/home_'
Ова го заменува com/index
со org/home
. Излезот ја прикажува изменетата URL адреса:
Outputhttp://www.example.org/home.html
Не заборавајте на конечниот разграниувач, или sed
ќе се жали. Ако ја извршите оваа команда:
- echo "http://www.example.com/index.html" | sed 's_com/index_org/home'
Ќе го видите овој излез:
Outputsed: -e expression #1, char 20: unterminated `s' command
Ајде да создадеме нова датотека за да вежбаме некои замени. Извршете ја следнава команда за да креирате нова текстуална датотека наречена song.txt
:
- echo "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..." > song.txt
Сега да го замениме изразот on
со напред
. Користете ја следнава команда:
- sed 's/on/forward/' song.txt
Излезот изгледа вака:
Outputthis 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
на командата за замена со тоа што ќе го ставите по множеството за замена:
- sed 's/on/forward/g' song.txt
Ќе го видите овој излез:
Outputthis 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
:
- sed 's/on/forward/2' song.txt
Овој пат другите линии се непроменети, бидејќи немаат втора појава:
Outputthis 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
на командата за замена за да ги испечатите линиите каде што се случила замената.
- sed -n 's/on/forward/2p' song.txt
Линијата што ја смени отпечатоците на екранот:
Outputyes, it goes on and forward, my friend
Како што можете да видите, можете да ги комбинирате знаменцата на крајот од командата.
Ако сакате процесот на пребарување да ги игнорира буквите, можете да го пренесете со знамето \i.
- sed 's/SINGING/saying/i' song.txt
Еве го излезот што ќе го видите:
Outputthis 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
, користете ја следнава команда:
- sed 's/^.*at/REPLACED/' song.txt
Ќе го видите овој излез:
OutputREPLACED 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
.
Бидејќи не ја знаете точната фраза што ќе се совпадне во низата за пребарување, можете да го користите знакот &
за да го претставите соодветниот текст во замената низа.
Да ставиме загради околу соодветниот текст:
- 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
и така натаму.
Во овој пример, ќе ги смениме првите два збора од секоја линија:
- sed 's/\([a-zA-Z0-9][a-zA-Z0-9]*\) \([a-zA-Z0-9][a-zA-Z0-9]*\)/\2 \1/' song.txt
Ќе го видите овој излез:
Outputis 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
како два збора во петтиот ред.
Ајде да го подобриме регуларниот израз за да бидеме попрецизни:
- sed 's/\([^ ][^ ]*\) \([^ ][^ ]*\)/\2 \1/' song.txt
Ќе го видите овој излез:
Outputis 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 команди.
Во следната статија од оваа серија, ќе истражите некои понапредни функции.