Portál AbcLinuxu, 9. května 2025 23:44

Dotaz: Jak odstranit znaky z proměnné pomocí shell\bash

21.9.2013 12:54 Lubosh
Jak odstranit znaky z proměnné pomocí shell\bash
Přečteno: 1165×
Odpovědět | Admin
DD, poradil by prosím nějaký odborník na shell či bash, jak z proměnné $FOO odstranit všechn mezery a tabulátory před prvním znakem a všechn mezery a tabulátory za posledním znakem. Určitě existuje spousta řešení, no můj problém je v tom, že vyžaduji co od tak pomalého shellu co nejrychleší zpracování, jedná se o položky jejichž počet běžně přesahuje 5 nul :-( Děkuji za každou pomoc.
Nástroje: Začni sledovat (0) ?Zašle upozornění na váš email při vložení nového komentáře.

Odpovědi

21.9.2013 13:11 Kit
Rozbalit Rozbalit vše Re: Jak odstranit znaky z proměnné pomocí shell\bash
Odpovědět | | Sbalit | Link | Blokovat | Admin
Především je potřeba takové údaje nestrkat do $FOO, ale použít přímo datový proud ze zdroje. Pak už je to jednoduché
zdroj_dat | sed -e 's/^\s*//' -e 's/\s*$//'
Shell není pomalý. Pomalé jsou jen zbytečné cykly v něm.
21.9.2013 13:36 Lubosh
Rozbalit Rozbalit vše Re: Jak odstranit znaky z proměnné pomocí shell\bash
:-D Věřím, že pomalejší řešení už neexistuje...
21.9.2013 13:52 Kit
Rozbalit Rozbalit vše Re: Jak odstranit znaky z proměnné pomocí shell\bash
Je fakt, že na mém notebooku to pro 10M záznamů (testovací soubor měl 230 MB) trvalo minutu. Určitě existuje rychlejší řešení.
21.9.2013 17:13 Lubosh
Rozbalit Rozbalit vše Re: Jak odstranit znaky z proměnné pomocí shell\bash
Tak to máš patrně nějaký kouzelný notebook ;-) Při použití tvého kódu na železe s 2xCPU, 16GB RAM při zpracování 10000 položek se dostávám na čas 6,5minut...
21.9.2013 18:01 Kit
Rozbalit Rozbalit vše Re: Jak odstranit znaky z proměnné pomocí shell\bash
Můj notebook má 2 GB RAM a procesor Core 2 Duo na 2 GHz. Jak vidíš, hrubou silou to asi nedělám.
21.9.2013 17:17 Lubosh
Rozbalit Rozbalit vše Re: Jak odstranit znaky z proměnné pomocí shell\bash
A velikost mého souboru je jen 300kB ;-)
21.9.2013 17:20 Kit
Rozbalit Rozbalit vše Re: Jak odstranit znaky z proměnné pomocí shell\bash
Musíš vypustit tu proměnnou $FOO. Ta to strašně brzdí.
21.9.2013 17:32 Lubosh
Rozbalit Rozbalit vše Re: Jak odstranit znaky z proměnné pomocí shell\bash
Nedokážu vypustit proměnnou $FOO, přece potřebuji s tou položkou co jsem u ní ořezal mezery i nadále pracovat, patrně si nerozumíme, nebo nerozumím já tobě :-(
21.9.2013 17:34 Kit
Rozbalit Rozbalit vše Re: Jak odstranit znaky z proměnné pomocí shell\bash
$FOO je jen nějaký mezičlánek, který plníš daty. Odkud bereš data? Ze souboru nebo z výstupu nějakého procesu?
21.9.2013 17:50 Lubosh
Rozbalit Rozbalit vše Re: Jak odstranit znaky z proměnné pomocí shell\bash
$FOO je jen nějaký mezičlánek, který plníš daty.
ano, přesně tak
Odkud bereš data? Ze souboru nebo z výstupu nějakého procesu?
Data beru z pole

21.9.2013 17:53 Kit
Rozbalit Rozbalit vše Re: Jak odstranit znaky z proměnné pomocí shell\bash
Pole v Bash je jeden velký nesmysl. Jak se ta data do toho pole dostala? Odkud se tam tak náhle objevila? To pole vůbec nemělo vzniknout.
21.9.2013 18:02 Lubosh
Rozbalit Rozbalit vše Re: Jak odstranit znaky z proměnné pomocí shell\bash
Pole se načítá ze souboru..
21.9.2013 18:16 Kit
Rozbalit Rozbalit vše Re: Jak odstranit znaky z proměnné pomocí shell\bash
No vida! Takže místo načítání ze souboru do pole uděláš tohle:
sed -e 's/^\s*//' -e 's/\s*$//' <soubor.txt
Leze to z tebe jak z chlupaté deky. Bílé znaky na začátku a na konci řádku bychom měli vyřešeny, co s těmi daty budeš dál dělat? Pokud je jen budeš chtít uložit do dalšího souboru, stačí na konec uvedeného řádku ještě přidat přesměrování
>druhy_soubor.txt
Předpokládám však, že je asi budeš chtít nějak zpracovat. Co to bude?
21.9.2013 18:33 Lubosh
Rozbalit Rozbalit vše Re: Jak odstranit znaky z proměnné pomocí shell\bash
A to je ten kámen úrazu ;) budu je ukládat zpět do jiného souboru, jenže důvod proč jsem takové řešení nikdy nerealizoval byl ten, že jsem nenašel způsob, jak získat z jednoho řádku dva řádky na výstupu.. Sice se nabízelo IFS ale to už je časově úplně špatně.. Jinak jsem se teď dostal s časem < 12sec. to je sakra rozdíl...
21.9.2013 18:41 Kit
Rozbalit Rozbalit vše Re: Jak odstranit znaky z proměnné pomocí shell\bash
To je celý problém? Když popíšeš, co vlastně potřebuješ, napíšu ti řešení na jeden řádek. Takže jakým způsobem chceš ten jeden řádek ze vstupu rozepsat na dva řádky na výstupu?
21.9.2013 18:58 Lubosh
Rozbalit Rozbalit vše Re: Jak odstranit znaky z proměnné pomocí shell\bash
Tak zkusím uvést příklad, mám soubor1 ve kterém je
  Text      /tmp/a     
        Nějaký text /tmp/b     
  Nějaký jiný text            /tmp/c            
a potřebuji dostat soubor2 ve kterém bude
"Text-a" "/tmp/a" "Nějaký složka-b" "/tmp/b" "Nějaký jiný text-c" "/tmp/c"
to je vše.. ;)
21.9.2013 19:17 Kit
Rozbalit Rozbalit vše Re: Jak odstranit znaky z proměnné pomocí shell\bash
Aha, takže máš text na více řádcích, které potřebuješ sloučit do jednoho řádku. To nebude tak složité. Ještě kdybych tak věděl, podle čeho rozpoznám, zda je na vstupu první, druhý nebo třetí řádek, protože na výstupu podle toho budu určovat, na které pozici to bude.

Z mého pohledu máš na prvním řádku dvě slova, rozpoznám ho podle slova "Text". Druhý řádek rozpoznám podle slov "Nějaký text" a má tři slova. Třetí bych mohl rozpoznat podle slov "jiný text". S příchodem třetího řádku vyprodukuji na výstupu uvedený řetězec.

Asi na ten program budu potřebovat tři řádky, aby se neztratila přehlednost. Je to zadání OK? Ať to pak nemusím zbytečně předělávat.
21.9.2013 19:27 Lubosh
Rozbalit Rozbalit vše Re: Jak odstranit znaky z proměnné pomocí shell\bash
No ten text je jen smyšlený, tudíž se podle něj nelze řídít :-( čili jediný způsob bude vložit oddělovací znak?
21.9.2013 19:36 Kit
Rozbalit Rozbalit vše Re: Jak odstranit znaky z proměnné pomocí shell\bash
Cokoli, co se dá detekovat. Ustálený řetězec, klíčové slovo, lomítko, rovnítko. Něco, podle čeho poznám, zda ten řádek bude první, druhý nebo třetí. Mohu také detekovat posloupnosti pořadových čísel řádek 1,4,7 - 2,5,8 - 3,6,9...

To vše je možné. Jenom potřebuji vědět, podle jakého pravidla rozpoznám kterou část textu. Například teď jsem si udělal funkční řešení
awk '!/jiný/ {printf($0)} /jiný/ {print($0)}' <data.txt
které však nebude správné, protože jsi problém specifikoval příliš vágně. Navíc jsem tam neořezal bílé znaky na začátku a na konci, ale to asi v tuto chvíli tolik nevadí.
21.9.2013 20:36 Lubosh
Rozbalit Rozbalit vše Re: Jak odstranit znaky z proměnné pomocí shell\bash
Může to být takto?
Text   .   /tmp/a     
        Nějaký text ./tmp/b     
  Nějaký jiný text .           /tmp/c  
21.9.2013 20:56 Kit
Rozbalit Rozbalit vše Re: Jak odstranit znaky z proměnné pomocí shell\bash
Může, ale tečka bývá nevýhodná, protože je speciální znak. Navíc mám obavu, zda se nevyskytne v textu. Mnohem lepší by byl třeba středník.

jak na to koukám, tak pořadí řádek budu asi muset rozpoznat podle stringů "/tmp/a", "/tmp/b" a "/tmp/c". Pokud to jsou fixní texty a jsou na konci řádku (plus pár nevýznamných bílých znaků), tečku ani jiný oddělovač potřebovat nebudeme.
21.9.2013 21:00 Lubosh
Rozbalit Rozbalit vše Re: Jak odstranit znaky z proměnné pomocí shell\bash
Právě že ne, v tomto případě může být za tečkou cokoli co nemusí začínat vůbec znakem "/" tak se ani nemusí jednat o adresář "tmp". Zkusíme to ze středníkem ;)
21.9.2013 21:06 Kit
Rozbalit Rozbalit vše Re: Jak odstranit znaky z proměnné pomocí shell\bash
Podle čeho tedy poznám, zda se jedná o první, druhý či třetí řádek?
21.9.2013 21:13 Lubosh
Rozbalit Rozbalit vše Re: Jak odstranit znaky z proměnné pomocí shell\bash
To znát nepotřebuješ, vždy to bude takto
foo ; bar #ŘÁDEK 1
foo ; bar #ŘÁDEK 2
foo ; bar #ŘÁDEK 3
foo ; bar #ŘÁDEK 4
a výstup do uvozovek a vše na jeden řádek...
21.9.2013 21:20 Kit
Rozbalit Rozbalit vše Re: Jak odstranit znaky z proměnné pomocí shell\bash
Ale na pátém řádku bude první řádek dalšího záznamu. Před chvílí jsi měl záznam ze tří řádek, teď ze čtyř. Psal jsi, že těch řádek máš 10000. Které chceš spojit a které ne?
21.9.2013 22:44 Lubosh
Rozbalit Rozbalit vše Re: Jak odstranit znaky z proměnné pomocí shell\bash
Ale já nikdy o žádném spojení nepsal.. Zkusím to ještě jednou, s čísly

soubor1 (zdroj (5 000 000 řádků - tady je prvních 7)) místo každého čísla může být cokoliv mimo středníku...
   1 ; 5
88; 9
15       ; 1
87 ; 11
     2 ; 1
89                ; 55
1    ;88
soubor2 (výstup)
"1" "5" 
"88" "9" 
"15" "1" 
"87" "11" 
"2" "1" 
"89" "55" 
"1" "88"
nebo klidně i takto, je to fuk
"1" "5" "88" "9" "15" "1" "87" "11" "2" "1" "89" "55" "1" "88"
22.9.2013 09:24 potato
Rozbalit Rozbalit vše Re: Jak odstranit znaky z proměnné pomocí shell\bash
Tohle se udělá triviálně:
sed 's/[ \t]*;[ \t]*/" "/g;s/^[ \t]*/"/;s/[ \t]*$/"/;'
Pokud už to je konečně skutečné zadání, tak proč jsi to proboha nemohl napsat o třicet příspěvků dřív?
22.9.2013 09:40 Kit
Rozbalit Rozbalit vše Re: Jak odstranit znaky z proměnné pomocí shell\bash
Něco podobného dostal jako úplně první odpověď. Myslel si, že to bude pomalé.
22.9.2013 10:55 potato
Rozbalit Rozbalit vše Re: Jak odstranit znaky z proměnné pomocí shell\bash
Jo, to už jsem nějak pozapomněl. Sed sice nemusí být nejrychlejší možné řešení, nicméně zpracovává v tomto případě jeden řádek asi 1 µs, s awk (RS nastaven rovnou na správný regexp) dostávám podobný čas. Od interpretovaných regulárních výrazů těžko čekat víc...
22.9.2013 11:03 Kit
Rozbalit Rozbalit vše Re: Jak odstranit znaky z proměnné pomocí shell\bash
Pokud nechce psát vlastní aplikaci v C, tak sed či awk je pro něj asi nejdostupnější a nejelegantnější řešení. I rychlost je podle mne velice slušná a pro mnoho aplikací naprosto vyhovující. Jenom se ten sed nesmí volat v bashovém cyklu pro každý řádek...
22.9.2013 11:24 potato
Rozbalit Rozbalit vše Re: Jak odstranit znaky z proměnné pomocí shell\bash
Pokud by to bylo něco, co se bude provádět fakt často s neměnným formátem dat a záleží na rychlosti, tak s běžnými postupy se v C lze pohodlně dostat pod 100 ns/řádek (zkoušel jsem). Pak už je to otázka, kolik času programátora má smysl obětovat na low-level optimalizace úlohy typu přepisování středníků na uvozovky. Nejspíš žádný, pokud to nebere jako intelektuální cvičení...
22.9.2013 11:30 Kit
Rozbalit Rozbalit vše Re: Jak odstranit znaky z proměnné pomocí shell\bash
Uvozovky ... tak mě napadá, jestli z toho nechce dělat SQL inserty...
22.9.2013 11:36 potato
Rozbalit Rozbalit vše Re: Jak odstranit znaky z proměnné pomocí shell\bash
To by snad mezi těmi řetězci chtěl jiné oddělovače než mezery. Ale třeba z něj po dalších deseti příspvěvcích vyleze, že ve skutečnosti chce...

Jinak tedy žádné z našich řešení neřeší escapování případných uvozovek ve vstupu, ale zda a jak je to zapotřebí ošetřit, to nikdo neví.
22.9.2013 11:48 Kit
Rozbalit Rozbalit vše Re: Jak odstranit znaky z proměnné pomocí shell\bash
Vůbec netušíme, jaké obskurnosti z něho vylezou, ale vhledem k tajnůstkaření bych to tipoval na vykrádání ceníků konkurence z jejich webů a nalévání do vlastní databáze. V tom případě by to celé bylo úplně špatně.

Na escapování uvozovek na vstupu by mohl přijít možná po druhém až třetím injection.
21.9.2013 21:24 Kit
Rozbalit Rozbalit vše Re: Jak odstranit znaky z proměnné pomocí shell\bash
Vlastně to skutečně znát nepotřebuji. Nic z toho znát nepotřebuji. Vlastně mě už ani nebaví z tebe tahat utajované zadání. A víš co? Dělej si to jak chceš.
21.9.2013 18:22 potato
Rozbalit Rozbalit vše Re: Jak odstranit znaky z proměnné pomocí shell\bash
To není popis, čeho se má dosáhnout. To je popis, jak se to [pravděpodobně] nemá dělat.

Data jsou v nějakém souboru a v nějakém dalším souboru nebo souborech mají po zpracování data zase skončit. Otázka je, jak je efektivně dostat z prvního místa do druhého. Kde je v předchozích vetách pole v shellu? Nikde.

Z popisu není jasné, co se s daty má dít dál, ale pro smyslupnou radu musíš napsat požadovaný konečný výsledek. Je velmi pravděpodovné, že efektivní řešení data přes žádné pole v shellu nepožene.
21.9.2013 18:26 Kit
Rozbalit Rozbalit vše Re: Jak odstranit znaky z proměnné pomocí shell\bash
Začínám tušit, že řešením problému bude jediný rychlý řádek s několika parametry. Je to však jak s číslem 42: Neznáme otázku.
21.9.2013 23:40 NN
Rozbalit Rozbalit vše Re: Jak odstranit znaky z proměnné pomocí shell\bash
Kite obdivuji tvou trpelivost ;).
22.9.2013 02:32 Michal Kubeček | skóre: 72 | Luštěnice
Rozbalit Rozbalit vše Re: Jak odstranit znaky z proměnné pomocí shell\bash
Odpovědět | | Sbalit | Link | Blokovat | Admin

Pominu-li, že (1) mezera i tabulátor jsou také znaky, takže před prvním znakem ani za posledním žádné mezery ani tabulátory být nemohou, a (2) pět nul je pořád jen nula, tak to, o co vám nejspíš jde, lze např. pomocí

  read FOO <<<"$FOO"

Pokud ty hodnoty ve skutečnosti čtete ze souboru, tak samozřejmě stačí rovnou

  while read line; do
      ...
  done <file

Založit nové vláknoNahoru

Tiskni Sdílej: Linkuj Jaggni to Vybrali.sme.sk Google Del.icio.us Facebook

ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.