sed - egy szó beillesztése egy meglévő sor elejére.

a következőt szeretném:

adott egy szöveg file amelyben engem a phn#-t megelőző sorok érdekelnek

az eredeti file így néz ki

valami szöveg van itt egy sorban
phn#

a phn#-hez hasonló címkét szeretnék a "valmi szöveg van itt egy sorban"
elejére beszúrni.
valahogy így

nam#valami szöveg van itt egy sorban
phn#

tehát nem új sorban, hanem beszúrni a matching sort megelőző sor eléjére.
Eddig sed-el kisérleteztem nem sok sikerrel.

sed '/adr#/i nam#' filename.txt

Ez nem beilleszti az előző sor elejére, hanem új sort hoz létre és abba írja nam#-t

köszönöm

Hozzászólások

sed 'N; /\nphn#/s/^/nam#/' filename.txt

cat demo.txt 
alma
valami szöveg van itt egy sorban
phn#
körte
valami más szöveg van itt egy sorban
phn#
szilva
sed 'N; /\nphn#/s/^/nam#/' demo.txt
alma
valami szöveg van itt egy sorban
phn#
körte
nam#valami más szöveg van itt egy sorban
phn#
szilva

Tehát nem jó.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

ez válasz akart lenni az előzőre, de hozzászólás lett, törölni nem tudtam

ha awk is johet:

#!/usr/bin/awk -f

BEGIN {
ins="beszur";
prevline="";
}
{
if( $1 == "phn#" ) printf("%s",ins);
if( NR > 1 ) printf("%s\n",prevline);
prevline = $0
}
END {
printf("%s\n",prevline);
}

Bocs, kicsit félreértettem, mit szeretnél, most alaposabban elolvastam. Amit írtam, ugyan nem azt csinálja, amit te szeretnél, de biztosan nem is azt, amit írtál rá. A címke elé tesz be egy sort, és abba teszi be a '\i' után megadott címkét. Neked persze nem egészen ez kell...

Én józan paraszti ésszel a következőképpen csinálnám:


Beolvasnék egy sort egy változóba
Ciklus indul EOF-ig
   Beolvasnám a következő sort egy másik változóba
   Ha a 2. változó elején ott a keresett string, az első változó sorát megfűszerezem a kívánt szöveggel
   Első változó kiírása a kimeneti fájlba
   Első változó legyen egyenlő második változó tartalmával
Ciklus vége
Második változó kiíratása a kimeneti fájlba

A szükséges vizsgálatokat (pl. van-e min. 2 sor) közben el kell végezni

openSUSE 12.2, vagy ami éppen jön.

Ezt a valaszt nem ertem. Mit szerettel volna meguszni? Ezt az algoritmust kell megcsinalni sed-del is. Ami nehezites, hogy kollega mindenfele valtozokrol beszelt, amije a sed-nek nincs. Ami konnyites, hogy van neki egy pattern space es egy hold space nevu terulete, ami kello fantaziaval felfoghato ket valtozonak. Javaslom a man 1 sed olvasgatast, kulonos tekintettel a nagybetus sed parancsokra, kb 4 vagy 5 van beloluk (sorban: D, G, H, N, P - ok, 5 db) es az x parancsra. Elkepzelheto, hogy szukseged lehet a cimke-kezelo parancsokra is (b, t, : parancsok), esetleg osszetett sed parancsokra ( { es } ), netan keresest cimkent hasznalni, esetleg negalt cimzest hasznalni.

Itt lejjebb mintha lenne valami hasonlo, most nincs nagy hangulatom kitesztelni, de persze ha jo es megerted, mar megerte.

Ami nehezites, hogy kollega mindenfele valtozokrol beszelt, amije a sed-nek nincs.

Senki nem állította, hogy sed-el kell megoldani!
A kérdés felvetésben a kérdező azt közölte, hogy Ő eddig sed-el próbálkozott.
Én csak az elvet írtam le.
A sed-hez fongom nincs, úgyhogy így tudtam csak "segíteni". :)
Peace

openSUSE 12.2, vagy ami éppen jön.

sed '/phn#/i nam#' filename.txt
oppsz, most olvasom, hogy a szöveg elé kell a nam#, ez pedig a szöveg és a phn# közé teszi. bocs.

Nem szép, nekem ez jött ki:

sed -r 's/^phn#/phn#/; T ment; x; s/(.*)/nam#\1/; b; : ment; x; 1 d; $ x;' demo.txt

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Már csak azt nem tudom, hogy ha már egyszer belenéz az ember a doksiba, és *semmi* szerepe nincs, akkor miért használ valaki ilyen-olyan (nem-szabványos) bővítményeket
- ha (.*) helyett \(.*\) szerepelne, akkor nem kellene a GNU-specifikus -r opció sem, simán menne e nelkul (ezt a formát azért kell tudni, mert a grep (-E nélkül is) tudja pontosan ugyanúgy, néha pedig jól jön az ilyesmi)
- meg ugye a T parancs a t helyett :-)

De hogy a ne csak a szájam járjon, itt az én megoldásom. Ezt bele egy fájlba, és hadd szóljon:
#nothing but an important comment
1h
2,${
/^phn#/{
x
s/^/nam#/
x
}
x
p
}
${ x ; p ; }

Az a megjegyzés sor tényleg szükséges, de ha nem ismered ezt a non-documented, de a gnu-sedben is működő dolgot, akkor adj át a sednek egy -n opciót is.
Agyon nem volt tesztelve. de úgy kb. stimmel.

Azért nem escape-eltem a zárójelet backslash-sel, mert szerintem így jobban olvasható a kód. Értem én, hogy jó a hordozhatóság, csak akkor meg minek fejlődjünk? Éppen ez az oka annak, hogy én a Bash hülyeségeit is kihasználom, ha már egyszer implementálták azokat. Simán le merek írni Bash scriptben olyasmit, hogy ((variable++)).

Mindezek mellett természetesen a hordozhatóság mellett is szólnak bőven érvek.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

A jobban olvashatosaggal kb egyetertek, de ha egyszer a nyelvben ezt ugy kell irni, akkor ugy kell irni. (Ez hasono, mint a muszaj, es a hulye.)
Ami miatt en altalaban ugrok az ilyesmire az az, hogy ritkan van leirva a teljes kornyezet - itt ugyan a sed le volt irva, de a futtatokornyezet (tehat az oprendszer) nem. Azaz valoszinuleg igaz, hogy Linux alatt akar az illeto ilyesmit, de egyaltalan nem biztos. (Speciel ha valahol az szerepel, hogy shell-script, akkor en nem bash-t feltetelezek, meg akkor sem, ha tobbsegeben arrol van szo - legalabbis a hupon.)
Es hogy mennyire nem mindegy a hordozhatosag, arra jo pelda, amikor bash-rol dash-ra csereltek (tan Debianban?) az alapertelmezett shellt, es egy halom regebben, figyelmetlenul megirt script elkezdett nem (jol) mukodni.)

Ezt is értem, csak akkor valóban minek van bash, GNU sed, gawk és a többiek. Ami a Debiant illeti, vagy át kell írni a scripteket, vagy visszacserélni a default shellt bash-re, de talán a legegyszerűbb, ha a script elején megmondjuk, mi legyen az interpreter, aminek futtatnia kellene. Én itt mindig bash-t mondok, nem pedig sh-t, arról nem is beszélve, hogy Fedorán bash a default shell, nem használok Debiant. :)

Tehát én továbbra is használom azon eszközöket, amelyek a rendelkezésemre állnak, hiszen úgy gondolom, azért vannak, hogy használjam, s nem azért, hogy sóvárgó tekintettel nézzek rájuk, majd egy sh kompatibilis megoldással megkerüljem.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

KAMINGAUT

Én is csak akkor onanizálok azzal, hogy a (k)sh egye a szkriptet, amikor itt kóricálok (elvégre akkor van idő), amikor valamit gyorsan kell csinálni - és mi nem olyan? - akkor szemrebbenés nélkül vetem be a legbashonlybb trükköket is azon az alapon, hogy ha a shebang megléte mellett se tehetem meg ezt külön aggodalom nélkül, akkor akár perl vagy tk szkriptet se írjak soha.

/KAMINGAUT

Kellene ket egymas alatti rekordot is latni, de nekem igy elso korben ez ugrott be:


awk '/^phn#/ { next; } { print "nam#" $0 }' file.txt > file2.txt

Probalj meg egy anonimizalt, de a fajl szerkezetet halalpontosan tukrozo peldat adni. Ha peldaul a "valami szoveg" ket soros, akkor olyan is legyen, ha van a rekordok kozt ures sor, az is legyen benne. Igy nagyon nehez okosat mondani.
--

Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant. | Gentoo Portal 

Mint irtam is, nincs leirva a kornyezet. Ha a rekordok ketsorosak, es nincs koztuk elvalaszto, akkor az en megoldasom is mukodhet a definicionak megfeleloen. Nem pontos a definicio, nincs pelda megadva, igy eltem az iroi szabadsag adta jogommal :-)
--

Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant. | Gentoo Portal 

Mellébeszélés. :)

echo -e 'elso sor\nmasodik sor' | awk '/^phn#/ { print $0; next; } { print "nam#" $0 }'
nam#elso sor
nam#masodik sor

A specifikáció lényege itt van:

tehát nem új sorban, hanem beszúrni a matching sort megelőző sor eléjére.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

A feladatkiiras erre a peldara vonatkozott:


$ echo -e 'valami szöveg van itt egy sorban\nphn#' | awk '/^phn#/ { print $0; next; } { print "nam#" $0 }'
nam#valami szöveg van itt egy sorban
phn#

A kimenet tokeletesen megegyezik az elvarttal. Test passed. Pontosan mi is a kerdes?
--

Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant. | Gentoo Portal 

Ja, ha így nézzük, akkor van egy egyszerűbb megoldásom is:

echo -e 'nam#valami szöveg van itt egy sorban\nphn#'

Azért remélem, az érthető vol a kiírásból, hogy van egy szövegfile, abban vannak néha markerek, s a markert megelőző sor elejére kell beszúrni valamit, a többi sort érintetlenül kell hagyni.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Álljon itt az utókornak egy perl egysoros megoldás:

perl -lne '$p="nam#".$p if /^phn#/;print $p if $.-1;$p=$_}{print' filename.txt

Legyen itt akkor egy sok soros Python is (biztos lehet szebben is):


#!/usr/bin/env python
import sys
stdow = sys.stdout.write
stdin_iter = iter(sys.stdin)

try:
	prev = next(stdin_iter)	
except StopIteration:
	prev = None

for line in stdin_iter:
	stdow('nam#' + prev) if line.rstrip('\n') == 'phn#' else stdow(prev)
	prev = line

if prev: 
	stdow(prev)

Btw. ez a Perl egysoros nem működik rendesen, az utolsó sort lenyeli.
Szerk.

♲♻♲

Ha mégis sed-et használnál:
sed ":a;N;$!ba;s/\n\([^\n]*\)\n\(phn#\)/\nnam#\1\n\2/g"

Némi magyarázat:
:a   :label
N    :Új sor
$!ba :Amíg nincs(!) vége($) a fájlnak, (b)ranch, vagyis nyomás az a labelhez.
Innentől nem soronként, hanem egyben manipulálható az egész fájl.

Az egyben manipulalahatosag jo otlet, felteve, hogy nem utkozol korlatokba. A POSIX specifikacio osszesen annyit ir elo, hogy legalabb 8192 byte meretu kell legyen a 'pattern space' illetve a 'hold space'. Innentol pedig mar a megvalositason mulik, hogy hajlando-e mondjuk dinamikus memoriafoglalassal dolgozni a vegtelensegig. (Nyilvan valamennyire rugalmasnak kene lennie, hisz lehetnek szep hosszu sorok a fajlban, ennek ellenere mivel a sed pont arra lett kitalalva, hogy ne kelljen beolvasni egy fajlt teljes egeszeben, itt azert en erzek nemi ellentmondast.)