Žádost o pomoc s VBS skripty (vyhledání>nahrazení, uložení do souboru)
Zdar chlapi, chci si v práci ulehčit práci.
Pokouším se vytvořit VBS skript, který by mi ze všech souborů s koncovkou .h(CNC programy) vytahal čísla nástrojů (17 TOOL CALL 112 Z S12000 DR+0
) " \d{3} ", vymazal duplikáty, seřadil je vzestupně pod sebe a uložil do souboru tools.txt do stejné složky. Vypotil jsem toto, ale musím ještě předtím udělat pár úkonů, abych dostal informace do vstupního souboru, z kterého se pak čísla vyexportují, ale už vůbec netuším, jak je seřadit. Já vím, že je tohle prasečina, že se nejdřív vytvoří další soubor a z něj pak až výsledný soubor
Const ForReading = 1
Const ForWriting = 2
Const ForAppending = 8
Set objShell = CreateObject("WScript.Shell")
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objRegEx = CreateObject("VBScript.RegExp")
Set objFile = objFSO.OpenTextFile("a.txt", ForReading)
Set outputfile = objFSO.CreateTextFile("nastroje.txt", True)
objRegEx.IgnoreCase = True
objRegEx.MultiLine = True
objRegEx.Global = True
objRegEx.Pattern = " \d{3} "
Results = ""
Do Until objFile.AtEndOfStream
line = objFile.ReadLine
Set colMatches = objRegEx.Execute(line)
If colMatches.Count > 0 Then
For Each strMatch in colMatches
outputfile.WriteLine strMatch
Next
End If
Loop
objFile.Close
Dim i, j
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objInputFile = objFSO.OpenTextFile(".\nastroje.txt", ForReading)
Set objOutputFile = objFSO.OpenTextFile (WorkingDir & ".\tools.txt", ForWriting, True)
Set objDict = CreateObject("Scripting.Dictionary")
j = 0
'On Error Resume Next
While Not objInputFile.AtEndOfStream
arrinputRecord = split(objInputFile.Readline, ",")
'Read input file with server names (Split is for later exspantion)
strFirstField = arrinputRecord(0)
if objDict.Exists(strFirstField) then
j=j+1
Else
objDict.add strFirstField, strFirstField
End if
Wend
colKeys = objDict.Keys
For Each strKey in colKeys
'wscript.echo "Result: " & strKey, objDict.Item(strKey)
objOutputFile.writeline objDict.Item(strKey)
Next
objInputFile.Close
objOutputFile.Close
'Report results
wscript.Echo "Hotovo, počet duplikátů : " & j
wscript.Echo "Výsledek v souboru tools.txt "
Pro spoustu z Vás je to brnkačka, tak bych Vás chtěl požádat, zda byste mi s tím
někdo nepomohl. Už jsem starej pes a než bych se VB naučil a ten skript dokončil,
byl bych v důchodu.
Na zkoušku přikládám pár programů (1.4MB)
S druhým skriptem už jsem totálně v lese. Měl by projet všechny *.h, najít pomocí
regex hodnoty jen v ose Z vyšší, než kterou zadám do vstupního pole a hodnotu přepsat
hodnotou v další vstupním poli. (Mám problém na stroji s tím, že programy jsou generovány
v CAMu a občas se stane, že při vyklonění otočného stolu se nástroj dostane na koncový
spínač, i když v simulaci V CAMu projde vše v pohodě... mašina se zastaví)
S tímhle ani nehnu, tak kdyby to někdo z vás vzal jako výzvu nebo malý úkol na procvičení,
byl bych mu moc vděčný. Kdyby to bylo ve VBS, tak bych si v tom mohl případně něco
málo upravit, nepohrdnu ale ani exe v jakémkoliv jiném jazyce.
24 L M03
25 L B+0.000 C+0.000 FMAX
26 FUNCTION TCPM F TCP AXIS POS PATHCTRL AXIS
27 L M03
28 L Z+42. FMAX
29 L X-16.182 Y-17.499 FMAX
30 L Z+12. FMAX
31 L
32 L X-16.182 Y-17.499 Z+12. FMAX
33 L Z+10.001 FMAX
34 L X-16.182 Y-17.499 Z+5.001 FMAX
Tady je náhled části souboru, tučně jsou zvýrazněny hodnoty, které potřebuji měnit,
zde např. hodnotu od Z+40 výš.
Hodnoty jsou kladná čísla od (+0.001 až +999.999). Regex (určitě by šel i zjednodušit):
Z\+[0-9]?[0-9]?[0-9]?.[0-9]?[0-9]?[0-9]?
Ono by snad i stačilo tohle: Z\+\d. , na jednom milimetru vůbec nezáleží
Předem děkuji převelice každému, kdo mi s tím pomůže.
VBS mi na to prijde strasne komplikovany, kdybych to mel resit ja (a nemohl to delat na linuxovem stroji), tak si nainstaluju cygwin, cimz ziskam linuxove nastroje (zdarma, legalne).
pak by reseni vypadalo asi takto:
1. priklad - vybrat 3 cislice tvorici cele slovo, seradit a vyhazet duplicity:
find -type f -name "*.h" -exec grep "\<\d{3}\>" {}\;|sed "s/.*\(\<\d{3}\>\).*/\1/"|sort -u>tools.txt
2. priklad:
find -type f -name "*.h" -exec sed -i "s/Z+\([456789]\d|\d{3,}\)\./Z+40./g"
Nevim, jestli vam to k necemu bude, ale pripadne zkuste aspon najit nejake rozumne nastroje na manipulaci textovych souboru, nez to psat vsechno od zacatku
cygwin potřeba není, grep i sed jsou pro windows i jako statické binárky.
sed.htm
grep.htm
Pánové díky moc za snahu, ale tudy asi cesta nepovede.
sed i grep jsem nainstaloval, pro jistotu jsem je i s knihovnami zkopíroval do adresáře se soubory, které chci projet.
Win příkaz find nepozná parametry v těch příkazových řádcích, nebude on taky součástí Linuxu? A za druhé se v těch přepínačích a parametrech absolutně nevyznám.
Ale úplně mě fascinuje, co jsou lidi schopni nacpat do jednoho řádku
Vse co jsem psal je, co bych pouzil na linuxu, tedy i find. Na Windowsjsem nesahnul uz radu let (mozna vic nez 10?), takze jak to je na nich netusim. Na druhou stranu to, co jsem tu napsal neni nic sloziteho, takze mozna zvladnete sestavit neco podobneho i s pouzitim Windows-only omezeni (nebo ten cygwin):
find -type f -name "*.h" -exec grep "\<\d{3}\>" {}\;|sed "s/.*\(\<\d{3}\>\).*/\1/"|sort -u>tools.txt
find : obecne hleda soubory a adresare
-type f : zajimaji nas pouze soubory
-name "*.h" : ktere konci na .h
-exec : na kazdy soubor spust nasledujici prikaz, {} nahrad za jmeno souboru
grep : obecne vybira radky podle nejakeho vzoru
"\<\d{3}\>" : zacatek slova, presne 3 cislice, konec slova (cili S12000 nevyhovuje, ackoli \d{3} splnuje)
{} : jmeno souboru nalezeneho od findu (treba pokus.h)
\; ukonceni seznamu parametru findu (ano, grep se svymi parametry je sam parametrem, find ho spusti na na kazdy soubor znovu a preda mu jmeno toho souboru misto {} )
| : zretezeni prikazu - vystup predchoziho (tedy radky obsahujici 3cislicova slova, zadne jine radky) predej jako vstup dalsimu prikazu
sed : stream editor (nahrazuje neco necim v textu)
"s/.*\(\<\d{3}\>\).*/\1/" : regularni vyraz, co chceme nahradit cim "s/vzor/nahrada/[parametry]"
s : substitude - nahrad. nasleduje znak, ktery ODDELUJE vzor a nahradu a pripadne parametry
/ : to je ten znak - pouzivame lomitko. Pokud se nam lomitko nelibi, muzeme poucit neco jineho, treba "s@vzor@nahrada@"
: nasleduje vzor:
.* : . je libovolny znak, * predchozi v libovolnem poctu (0..nekonecno) - cili libovolny retezec s libovolnym obsahem
\(neco\) : neco je vec co nas zajima, v nahrade na nej odkazujeme pomoci \1 (u dalsi zavorky \2, \3 a tak dal)
\<\d{3}\> : neco je 3cislicove slovo (viz grep)
.* : nasleduje zase libovolny retezec
/ : oddelovac stejny jako byl za tim "s" na zacatku - nasleduje nahrada
\1 : z celeho radku nas zajima jen to v zavorce (3cislicove slovo), nic vic nechceme
/ : opet oddelovac - nasleduji volitelne parametry (zadne nepotrebujeme, zadne tedy nezadavame)
| : zretezeni prikazu - sed dostava zajimave radky, z nej padaji uz jen ty trojcisli
sort : tridici program na vystup vypise setrideny (po radcich) vstup
-u : --unique vypisuje pouze unikatni vzorky, je-li vic stejnych vypise prvni, ostatni preskoci
> : presmerovani vystupu do souboru (sort vypisuje kyzeny vysledek, my ho nekam ulozime)
tools.txt : jmeno souboru (do ktereho to vypisujeme)
Jak je videt, neni to zadna magie, jen pouziti naprosto beznych nastroju, ktere ma snad kazda linuxova distribuce, zpusobem, pro ktery jsou urceny. Pri prepisovani pro Windows muzou nastat nejruznejsi problemy (nejsou prislusne programy, nektere retezce se pokusi interpretovat primo samy Windows a tak podobne, ale v principu by to melo jit nejak udelat. Cygwin odstranuje prave vetsinu techto problemu, i kdyz je to ponekud s kanonem na vrabce, tak jeho naroky jsou male.)
2. find -type f -name "*.h" -exec sed -i "s/Z+\([456789]\d|\d{3,}\)\./Z+40./g"
find -type f -name "*.h" -exec : viz vyse - najdi *.h a neco s tim udelej
sed : nahrazovani
-i : in-place - udela zmeny primo v souboru, misto aby ho nechal netknuty a vypsal vysledek. Proste ten soubor zedituje
"s/vzor/nahrada/parametry" : viz vyse - parametr "g" (global) znamena, ze to udela i pro vic vyskytu na jednom radku
Z+ : musi to zacinat "Z+" (asi souradnice zet a kladne znaminko)
\(neco\) : o tohle nam jde - viz vyse
[456789]\d : jeden ze znaku 456789 nasledovany cislici (cili 40..99)
| : jako cast regularniho vyrazu znamena NEBO (OR)
\d{3,} : cislice v poctu 3 a vice 100..9999999999999...
\. : tecka. Protoze tecka sama o sobe predstavuje "libovolny znak" tak ji escapujeme backslashem. Takze tato dvojice znamena "tecka osobne"
/ :oddelovac
: cili vzor je napriklad Z+123. obsah zavorky pak je 123 - jdeme to nahradit vyrazem
Z+40. : zet plus 40 tecka, cili obsah zavorky proste nepouzijeme, kdyz je to Z+40. a vic, tak tam dame Z+40.
/ : opet oddelovac
g : parametry - globalne - pokud by radek byl "Z+50. X+60. Z+70." tak se nahradi oba vyskyty a dostaneme "Z+40. X+60. Z+40."
vsechno je to popsane v "man" strankach pro dane prikazy - pokud delate nejake podobne upravy casteji, tak vazne doporucuju si sehnat linux/cygwin a tohle nastudovat. usetri to strasnou spoustu zbytecne driny
Jinak samozrejme muzes pouzit jen tu ideu samotnou a poskladat to z jinych prikazu, ktere mas po ruce, akorat mi prijde zbytecne programovat takovehle veci, kdyz pro ne nastroje existuji uz 20 let nejmin.
Jo a ta 2. je samozrejme trik, pokud bys mel jinou hranici, musis upravit jak tech Z+40., tak ten vyraz pred tim (napriklad pro 53 takto: 5[3456789]|[6789]\d|\d{3,} - cili 53-59|60-99|100 a vic)
Tak tohle je opravdu vyčerpávající odpověď, díky
Nainstaloval jsem ten Cygwin, jen netuším, jak se dostat k disku a cestě umístění těch programů co se mají prohledávat a jak ten řádek s příkazy spustit (nejspíš v přík.řádku). Při spuštění cygwin se spustí console, ale příkazy Linuxu neovládám. V man hledám, ale když nevím co mám přesně hledat, tak je to těžký Což o to, já bych se třeba naučil, jak s tím pracovat, jenže mám ještě dva kolegy, kteří mají "pár" let do důchodu a nejsou v problematice PC tak zběhlí. Proto jsem chtěl, aby to byl nějaký script nebo soubor co se jen spustí a sám to provede. U druhého scriptu to samozřejmě bude chtít vstup uživatele.
Ještě jednou moc díky
pwd - print working directory (aktualni adresar)
ls - list (v DOSu dir) vypise obsah adresare
cd adresar - change directory - prejde do adresare
man prikaz - manual k prikazu (viz tez man man)
apropos slovo - vypise ktere prikazy ho maji v man-u v hlavicce (nevim, je-li v cygwinu)
mc - midnight commander - obdoba nortona, volkova a podobnych dvouoknovych commanderu - velice uzitecne
( ctrl+o zapne/vypne panely, F1 help, da se najit ovladani)
prikaz muzes ulozit do souboru a pak spustit, ale musi mit priznak spustitelny (v mc CtrlX C)
parametry toho skriptu se znaci $1 $2 $3 .... ale u toho druheho si asi napises nejaky kratky program, co to z parametru nageneruje
Linux pouziva / nikoli \ v adresarich, nevim jak cygwin.
Asi by melo jit
cd "C:/muj/adresar/nekde"
Přidal jsem do Path ve win adresář c:\cygwin64\bin\ takže mi to grep a sed spustí, ale problém je v tom, že find bere jako interní příkaz win. Zkopíroval jsem linux find pod názvem lfind. Po spuštění následující hláška:
d:\vbs\el>lfind -type f -name "*.h" -exec grep -e "\<\d{3}\>" {}\; | sed "s/.*\
(\<\d{3}\>\).*/\1/" | sort -u 1>tools.txt
-uSyst'm nem§e nal'zt uvedeně soubor.
Nevím co za soubor nemůže najít
osobně nejsem moc pro takové mixování lin a win prostředí, výjimka jsou mocné textové procesory sed a awk plus prohledávač grep (windowsí ekvivalent find je proti němu chudý příbuzný, protože neumí reguláry)
jedna technická: regulární výrazy umí findstr.
ale k tomu není ve win nápověda, poslepoval jsem to v životě jednou.
místo příkazu find (který ve Windows/DOS) funguje jako textový prohledávač je třeba použít příkazu dir a příkazu for.
např. výpis všech souborů (ne adresářů) s koncovkou .h z c:\cnc, progrepování a zápis výsledků do soubor.txt
Tohle by taky možná šlo, ale nevím jestli zkouším správně. Pokud napíšu jen tohle bez grepu, neměl by tenhle
příkaz vlastně zkopírovat obsahy všech .h souborů do jednoho souboru?
Pokud ano, tak napíše chybu, že DO nebyl nyní očekáván.
možná je tam chyba, psal jsem to zpaměti.
viz for /?
Tak jsem se dopracoval jen k vyřešení exportu všech řádků ze všech souborů obsahujících "3číslice ohraničené mezerami"
V grepu jsem musel použít přepínač -P, aby mi to bralo tenhle regexp " \d{3} ", gilhadův mi to nebralo vůbec.
Jen ten sed nevím jak zprovoznit, nebere mi to vůbec regulární příkazy nebo je neumím zapsat ve správném formátu.
Linuxový sort jsem našel, ten mi funguje
Jako nouzové řešení beru spustit baťák, v kterém by se vyexportoval temp soubor, který bych prohnal vyvoláním mého VBS scriptu a exportu do souboru, temp soubor pak smazat
PS: za mlada mi říkali zkomoleninou tvýho nicku... Kačůd To ještě skoro nikdo anglicky neuměl
V príkaze sed sa nedajú použiť také konštrukcie, na ktoré si zvyknutý z bežných zápisov (PCRE), takže také \d tam nebude fungovať. Druhá vec je, že ten grep tam už ani nie je potrebný, keď už používaš taký silný nástroj, ako je sed - použiješ prepínač -n a modifikátor /p. Takže namiesto kombinácie grep a sed ti postačí takýto príkaz:
Taky moc děkuju , tohle funguje na výbornou, jen jsem přidal ještě i 4-místné číslo
Jdu zkusit vytvořit novou verzi
Teď už by to mělo jít i bez toho VBS scriptu
EDIT:
No vida
Měl bych na Tebe jednu otázku ohledně druhého scriptu, kde potřebuju měnit hodnoty v ose Z (pokud je vyšší než nějaká hodnota, změnit na nižší). Tohle mi tak nějak funguje, jen mi to ke každému vygenerovanému souboru udělá ještě dva další (jeden .bak, druhý nějaký automaticky generovaný název sedxxxxx.)
Výraz k vyhledání si budu muset upravovat ručně, k nahrazení stačí proměnná v SET= (vyzkoušeno).
Mohl bys mi s tím pomoci prosím? Nevyznám se moc (skoro vůbec) v přepínačích a modifikátorech, určitě tam mám něco špatně.
Jen potřebuju, aby se hodnota změnila přímo v souboru, případně může udělat soubor záložní.
Děkuji moc
Keď má sed priamo upravovať súbor, nad ktorým pracuje (prepínač -i), tak si vytvorí dočasný súbor, ktorý na konci vymaže. Zrejme počas spracovania spadol a tak po sebe neupratal. Príkaz sed nepoužívam zas tak často, ale na Windowse som s ním na takýto problém ešte nenarazil. Zrejme závisí od vstupov, takže ak sem dáš príklad vstupného súboru a presný príkaz, ktorý si spustil, tak si to môžem u seba otestovať.
Tučné hodnoty měním scriptem v souboru _start.bat na Z+10.
Použil jsem sed z UnxUtils a už je to ok, dělá už jen bak-y.
Už vymýšlím blbosti, ale zeptám se: Lze jedním příkazem sed provést více vyhledání na více řádcích?
Příklad:
Mám program, z kterého chci vytáhnout číslo nástroje T a za něj doplnit info o nástroji (112 D=12.00 R=1.00 (d12R1-l55-Kieninger))
Oba výrazy text najdou, ale jen každý zvlášť
^.*NASTROJ : \(.*$\)
^.* \([0-9]\{3,4\}\) Z.*$
Jde to nějak ošetřit, aby nalezl najednou oba výrazy a zapsal je do jednoho řádku?
...jsou to kouzla a čáry...
EDIT: Tak na to kašlu, zjistil jsem, že když je pro jeden nástroj více drah, tak už se v programu nevyskytuje volání nástroje, je tam jen popis. Musely by být splněny obě podmínky najednou (např.když najde popis, musí do 3.řádku najít ještě číslo nástroje. Pro mě nemyslitelné, vzdávám to
Ještě jednou moc díky všem poradcům za rady a hlavně trpělivost
Pomocou sedu sa dá aj spracovať dva riadky tak, ako si pôvodne chcel:
Prvý výraz:
Druhý výraz:
So sedom sa dá toho robiť naozaj veľa.
Edit: Aha, ty si to chcel vlastne v opačnom poradí. Tak potom takto:
Dík za pomoc, za celý den vyzkoušel takových věcí a kombinací... až mi vyšlo tohle:
Výstup vypadá takhle:
112 | D=12.00 R=1.00 (d12R1-l55-Kieninger)
115 | D=6.00 R=3.00 (d6R3-L40-Kieninger)
136 | D=4.00 R=0.50 (d4R0,5-d4 v delce 40 celkem vylozeno 50 - WEDCO)
212 | D=12.00 R=1.00 (d12R1-l55-Kieninger)
.
.
.
Ještě si pohraju s formátováním aby mi to sedělo do tabulky a bude to přesně jak jsem potřeboval.
Sice to vůbec nechápu, ale hlavní je, že to chodí tak jak má
Tisíceré díky, moc jsi mi pomohl
První script jsem už "tak nějak" vyřešil, už konečně dělá to co má. Jen jsem přidal do výpisu řádky s podtržítky a svislítky, aby se na papír mohlo psát většími písmeny. Kdybych měl čísla jen pod sebou tak bych použil jen cut místo sed. Už do toho začínám trochu pronikat, mám o zábavu na dlouhou dobu postaráno.
Tohle je výpis, takhle mi to vyhovuje:
Akorát sed nerozumí mým regulárním výrazům, ať to zkouším jak to zkouším Zkoušel jsem testovat výrazy v RegexBuddy, ale pro GNU nejspíš neplatí jako zástupný znak pro číslici \d . Zkoušel jsem v sed-u psí kusy, ale stejně se nepovedlo. Není potřeba nějaká externí dll?
Jinak Vám dvěma moc děkuju, bez Vás bych to dohromady nedal
EDIT: oprava, ve _start.bat má být (@lsort -g -u)
jen technická - samotné regulární výrazy nejsou na 100% stejné ve všech implementacích. Je třeba se podívat do nápovědy ke konkrétnímu programu. U unixových nástrojů např. na manpages.
man-cgi
Sed.html
jinak velká pochvala za proaktivní přístup a samostudium!
Díky za pochvalu
No právě... že nejsou stejné. Prolezl jsem spoustu stránek ohledně sedu, grepu a reg.výrazů, moc chytrý jsem z toho nebyl. Sed používám ten z Tvého odkazu, ještě zkusím z UnxUtil nebo Cygwinu, třeba se nějaký chytne. Ty regulární výrazy bych potřeboval rozchodit kvůli vyřešení druhého scriptu, tam je opravdu potřebovat budu. Zatím musím vydejchat ten první
ale druhý skript je VBS, tam musíš použít syntax RegExp kódu VBS. (pokud jsem to pochopil správně)
Změny a rozdíly viz: vbscript.html
Ve VBS je to v pohodě, tuhle syntax tak nějak ovládám, používám ho i na makra v Notepad++ (taky mi tedy dává občas zabrat ). Hledám řetězec, který začíná mezerou, pak je 3až4-ciferné číslo, mezera a Z. To Z tam mám kvůli pozdější náhradě za nový řádek "náznak tabulky".
I ten grep, když mu dám parametr -P tak mi " \d{3,4} Z" vezme a řetězec najde.
Jen ten zatrsakr sed ne Ona je spousta příkladů jak sed použít, bohužel většina jen při práci s textem. Už mi z toho občas hrábě
a proč jej nezkusíš nahradit jednodušší formou?
"[0-9][0-9][0-9] Z"
Teď jsem ještě zkusil z posledních sil zkombinovat pár výrazů, aby aspoň něco sed vzal, vyšlo mi toto:
"mezera,číslo 100-1999,mezera,Z" nahradit řetězcem test. Akorát bych potřeboval nahradit vše ostatní kromě nalezeného výrazu. Ještě si s tim budu muset hodně pohrát a pochopit.
Tu mezeru na začátku taky potřebuju, jinak mi to najde i tohle (L X-0.224 Y+1.939 Z+11.437 B+1.889 C+96.618).
Ten sed využiju v druhém scriptu, tam už musím řetězec nahrazovat, tohle byl jen test.
obecně k problematice různých implementací regexpu:
http://www.nti.tul.cz/~satrapa/docs/regvyr/all.htm l
ten zbytek můžeš IMHO pořešit tímto:
Sed.html
Dík za info, konečně pochopitelná stránka v češtině, už je v oblíbených Jdu se vzdělávat