2015-12-07 4 views
6

मैं एक पाठ फ़ाइल है कि इस तरह से एक लंबी स्ट्रिंग से पहले लाइन ब्रेक जोड़ें:पाठ फ़ाइल में विशेष वर्ण के साथ स्ट्रिंग का पता लगाएं और प्रत्येक घटना

ISA*00*GARBAGE~ST*TEST*TEST~CLP*TEST~ST*TEST*TEST~CLP*TEST~ST*TEST*TEST~CLP*TEST~GE*GARBAGE*~ 

और मैं इसकी आवश्यकता इस तरह देखने के लिए:

~ST*TEST*TEST~CLP*TEST 
~ST*TEST*TEST~CLP*TEST 
~ST*TEST*TEST~CLP*TEST 

मैं पहली स्ट्रिंग को विभाजित करने के लिए हर ~ST पर एक लाइन जोड़ने की कोशिश की है, लेकिन मैं के लिए मुझे के जीवन ऐसा नहीं कर सकता। मैंने विभिन्न स्क्रिप्ट्स की कोशिश की है, लेकिन मैंने सोचा कि एक खोज/प्रतिस्थापन स्क्रिप्ट सबसे अच्छा काम करेगी।

@echo off 
setlocal enabledelayedexpansion 
set INTEXTFILE=test.txt 
set OUTTEXTFILE=test_out.txt 
set SEARCHTEXT=~ST 
set REPLACETEXT=~ST 

for /f "tokens=1,* delims=~" %%A in ('"type %INTEXTFILE%"') do (
    SET string=%%A 
    SET modified=!string:%SEARCHTEXT%=%REPLACETEXT%! 

    echo !modified! >> %OUTTEXTFILE% 
) 
del %INTEXTFILE% 
rename %OUTTEXTFILE% %INTEXTFILE% 

यहाँ मिले How to replace substrings in windows batch file

लेकिन मैं अटक कर रहा हूँ क्योंकि (1) विशेष वर्ण ~ कोड बिल्कुल काम नहीं करता है। यह मुझे इस परिणाम देता है:

string:~ST=~ST 

कोड "~ST" पीछे उद्धरण चिह्न का उपयोग कर यदि कुछ भी नहीं करता है। और (2) मैं यह नहीं समझ सकता कि ~ST से पहले लाइन ब्रेक कैसे जोड़ना है।

इसके लिए अंतिम कार्य सभी विभाजनों के बाद ISA*00*blahblahblah और ~GE*blahblahblah लाइनों को हटाना होगा। लेकिन मैं ~ST भाग पर विभाजन पर फंस गया हूं।

कोई सुझाव?

+1

बैच के साथ एक टिल्ड को बदलने के लिए कोई आसान तरीका नहीं है। जेआरईपीएल (बैच/जेस्क्रिप्ट हाइब्रिड) एक अच्छा समाधान है – jeb

+0

प्रारंभिक और अंतिम भागों को पहचानने के मानदंड क्या हैं जिन्हें हटाया जाना चाहिए? '~ एसटी' की पहली घटना से पहले सब कुछ शुरुआती हिस्सा है, और अंतिम भाग '~ जीई' और सब कुछ के बाद? और आपकी इनपुट टेक्स्ट फ़ाइल का आकार क्या है? – aschipfl

उत्तर

1

How can you find and replace text in a file using the Windows command-line environment?

यह विषय किसी आदेश पंक्ति से की जगह करने के लिए तरीकों की बहुत सारी शामिल हैं।

मेरा पसंदीदा Clay's Utilities for Win32 संग्रह से नि: शुल्क उपकरण Xchang32 उपयोग कर रहा है, क्योंकि यह भी बाइनरी फ़ाइलों के लिए इस्तेमाल किया जा सकता।

इस कार्य को कमांड लाइन का उपयोग करने के लिए है:

Xchang32.exe "Test.txt" "~ST" "^x0D^x0A~ST" 

^x0D एक गाड़ी वापसी के लिए हेक्साडेसिमल नोटेशन है।
^x0A लाइन-फीड के लिए हेक्साडेसिमल नोटेशन है।

का उपयोग क्यों कर रहे हैं Xchang32.exe उपकरण केवल मानक विंडोज आदेशों की बजाय फ़ाइलों में खोज और प्रतिस्थापित करने के लिए?

यह पूछने की तरह है कि एक बोर्ड में नाखून चलाने के लिए हथौड़ा का उपयोग क्यों करें और उदाहरण के लिए एक विकर्ण प्लेयर्स नहीं। एक विकर्ण प्लेयर्स के साथ एक बोर्ड में एक नाखून ड्राइव करना संभव है क्योंकि मैंने इसे पहले से ही एक बार किया है। लेकिन एक हथौड़ा का उपयोग करना इतना आसान है जो बोर्डों में नाखून चलाने के लिए डिज़ाइन किया गया है।

तो फ़ाइल में स्ट्रिंग को प्रतिस्थापित करने के लिए केवल मानक विंडोज कमांड का उपयोग करना संभव है हालांकि इसके लिए डिज़ाइन नहीं किया गया है। लेकिन Xchang32.exe जैसे एक निःशुल्क टूल का उपयोग करना बहुत आसान है जो वास्तव में इस कार्य के लिए डिज़ाइन किया गया है।

निम्नलिखित बैच फ़ाइल का उपयोग संपूर्ण कार्य के लिए GARBAGE अज्ञात स्ट्रिंग के साथ किया जा सकता है।

@echo off 
Xchang32.exe "Test.txt" "~ST" "^x0D^x0A~ST" >nul 
if errorlevel 1 goto :EOF 

setlocal EnableDelayedExpansion 

Xchang32.exe "Test.txt" "~GE" "^x0D^x0A~GE" >nul 

del "%TEMP%\Test.tmp" 2>nul 

for /F "usebackq skip=1 delims=" %%L in ("Test.txt") do (
    set "Line=%%L" 
    if "!Line:~1,2!" == "ST" echo %%L>>"%TEMP%\test.tmp" 
) 

move /Y "%TEMP%\Test.tmp" "Test.txt" 
endlocal 
3
@echo off 
setlocal EnableDelayedExpansion 

rem Set next variable to the number of "~" chars that delimit the wanted fields, or more 
set "maxTokens=7" 
rem Define the delimiters that starts a new field 
set "delims=/ST/GE/" 

for /F "delims=" %%a in (test.txt) do (
    set "line=%%a" 
    set "field=" 
    rem Process up to maxTokens per line; 
    rem this is a trick to avoid a call to a subroutine that have a goto loop 
    for /L %%i in (0,1,%maxTokens%) do if defined line (
     for /F "tokens=1* delims=~" %%b in ("!line!") do (
     rem Get the first token in the line separated by "~" delimiter 
     set "token=%%b" 
     rem ... and update the rest of the line 
     set "line=%%c" 
     rem Get the first two chars after "~" token like "ST", "CL" or "GE"; 
     rem       if they are "ST" or "GE": 
     for %%d in ("!token:~0,2!") do if "!delims:/%%~d/=!" neq "%delims%" (
      rem Start a new field: show previous one, if any 
      if defined field echo !field! 
      if "%%~d" equ "ST" (
       set "field=~%%b" 
      ) else (
       rem It is "GE": cancel rest of line 
       set "line=" 
      ) 
     ) else (
      rem It is "CL" token: join it to current field, if any 
      if defined field set "field=!field!~%%b" 
     ) 
    ) 
    ) 
) 

इनपुट:

ISA*00*GARBAGE~ST*TEST1*TEST1~CLP*TEST1~ST*TEST2*TEST2~CLP*TEST2~ST*TEST3*TEST3~CLP*TEST3~GE*GARBAGE*~CLP~TESTX 

आउटपुट:

~ST*TEST1*TEST1~CLP*TEST1 
~ST*TEST2*TEST2~CLP*TEST2 
~ST*TEST3*TEST3~CLP*TEST3 
+0

किसी ने मुझे बताया, कि एक अच्छे जवाब में भी एक अच्छा स्पष्टीकरण होना चाहिए। :-) – jeb

+0

@jeb: तुमने मुझे मिल गया! ** ';)' ** मैंने कोड में वर्णनात्मक टिप्पणी जोड़ दी ... – Aacini

0

~,-स्ट्रिंग प्रतिस्थापन वाक्य रचना %VARIABLE:SEARCH_STRING=REPLACE_STRING% में एक खोज स्ट्रिंग के प्रथम वर्ण के रूप में इस्तेमाल नहीं किया जा सकता क्योंकि यह सबस्ट्रिंग विस्तारको चिह्नित करने के लिए प्रयोग किया जाता है 0 (अधिक जानकारी के लिए set/? टाइप करें)।

आपकी टेक्स्ट फ़ाइल का मानना ​​है कि केवल टेक्स्ट की एक पंक्ति है और यह लगभग 8 केबीईटी के आकार से अधिक नहीं है, मुझे आपके कार्य को पूरा करने के लिए निम्न विकल्प दिखाई देता है। यह स्क्रिप्ट सबस्ट्रिंग प्रतिस्थापन वाक्यविन्यास %VARIABLE:*SEARCH_STRING=REPLACE_STRING% का उपयोग करता है;

@echo off 
setlocal EnableExtensions EnableDelayedExpansion 

rem initialise constants: 
set "INFILE=test_in.txt" 
set "OUTFILE=test_out.txt" 
set "SEARCH=ST" 
set "TAIL=GE" 

rem read single-line file content into variable: 
< "%INFILE%" set /P "DATA=" 
rem remove everything before first `~%SEARCH%`: 
set "DATA=~%SEARCH%!DATA:*~%SEARCH%=!" 

rem call sub-routine, redirect its output: 
> "%OUTFILE%" call :LOOP 

endlocal 
goto :EOF 

:LOOP 
rem extract portion right to first `~%SEARCH%`: 
set "RIGHT=!DATA:*~%SEARCH%=!" 
rem skip rest if no match found: 
if "!RIGHT!"=="!DATA!" goto :TAIL 
rem extract portion left to first `~%SEARCH%`, including `~`: 
set "LEFT=!DATA:%SEARCH%%RIGHT%=!" 
rem the last character must be a `~`; 
rem so remove it; `echo` outputs a trailing line-break; 
rem the `if` avoids an empty line at the beginning; 
rem the unwanted part at the beginning is removed implicitly: 
if not "!LEFT:~,-1!"=="" echo(!LEFT:~,-1! 
rem output `~%SEARCH%` without trailing line-break: 
< nul set /P "DUMMY=~%SEARCH%" 
rem store remainder for next iteration: 
set "DATA=!RIGHT!" 
rem loop back if remainder is not empty: 
if not "!DATA!"=="" goto :LOOP 
:TAIL 
rem this section removes the part starting at `~%TAIL%`: 
set "RIGHT=!DATA:*~%TAIL%=!" 
if "!RIGHT!"=="!DATA!" goto :EOF 
set "LEFT=!DATA:%TAIL%%RIGHT%=!" 
rem output part before `~%TAIL%` without trailing line-break: 
< nul set /P "DUMMY=!LEFT:~,-1!" 
goto :EOF 

निम्न प्रतिबंध इस दृष्टिकोण के लिए लागू: *SEARCH_STRING की पहली आवृत्ति के लिए सब कुछ मैच के लिए परिभाषित करता है

  • इनपुट फ़ाइल एक पंक्ति होता है;
  • इनपुट फ़ाइल का आकार लगभग 8 केबीईटी से अधिक नहीं है;
  • ~GE का बिल्कुल एक उदाहरण है, जो ~ST के सभी उदाहरणों के बाद होता है;
  • दो आसन्न ~ST उदाहरणों के बीच हमेशा कम से कम एक चरित्र होता है;
  • कोई भी विशेष वर्ण की तरह, फ़ाइल में होते हैं: अंतरिक्ष, टैब, ", %, !, =;
0

पहिया बदलने, एक regexp sed या JREPL.BAT के रूप में इस तरह के उपकरण की जगह का उपयोग न करें:

call jrepl "^.*?~ST(.+?)~GE.*$" "'~ST'+$1.replace(/~ST/g,'\r\n$&')" /jmatch <in.txt >out.txt 
संबंधित मुद्दे