2016-06-29 1 views
-1

Ich nehme eine M3U-Datei auf einer täglichen Basis auf, möchte aber einen Teil davon in eine andere Datei mit den wenigen Kanälen, die ich brauche, analysieren.Teil einer Textdatei in BAT extrahieren

Zum Beispiel habe ich meine m3U umbenannte Datei in TEST.TXT, die folgende fiktive Struktur sagen hat:

die Linie von „#EXTINF starrte erfassen
#EXTINF:0,ABC 
#live link 1 
#EXTINF:0,XYZ 
#live link 2 
#EXTINF:0,UVW 
#live link 3 

Ich möchte nur sagen: 0, XYZ“und sagen sie die Zeile darunter mit einem Output.txt am Ende wie folgt:

#EXTINF:0,XYZ 
#live link 2 

Ich weiß, dass man die For-Schleife benutzen muss, aber ich bin ein bisschen noob in diesem Bereich.

+0

Ja, es könnte weiße Leerzeichen haben. – GDrago

+0

Ist es möglich, dass der Teil 'XYZ' Leerzeichen enthält? Kann es in Ihren Beispieldaten nachgestellte Leerzeichen geben? – aschipfl

Antwort

0

ich es so tun würde, ist die .m3u Datei angenommen nicht wissen Räume in den Zeilen mit vorangestellten #EXTINF enthalten Hinter, wie Ihre Beispieldaten haben:

@echo off 
setlocal EnableExtensions DisableDelayedExpansion 

rem // Define constants here: 
set "FILE=%~1" 
set "HEADER=#EXTM3U" 
set "PREFIX=#EXTINF" 
set "MATCH=%~2" 

set "FLAG=" 
for /F usebackq^ delims^=^ eol^= %%L in ("%FILE%") do (
    if defined FLAG (
     echo(%%L 
     set "FLAG=" 
    ) 
    for /F "delims=:" %%P in ("%%L") do (
     if "%%P"=="%HEADER%" (
      echo(%%L 
     ) else if "%%P"=="%PREFIX%" (
      set "LINE=%%L" 
      setlocal EnableDelayedExpansion 
      if /I "!LINE:*,=!"=="!MATCH!" (
       echo(!LINE! 
       endlocal 
       set "FLAG=#" 
      ) else endlocal 
     ) 
    ) 
) 

endlocal 
exit /B 

Rufen Sie das Skript wie folgt, es angenommen wird als extract-entry.bat gespeichert:

extract-entry.bat "input_file.m3u" "XYZ" > "output_file.m3u" 

Das Skript für Zeile der gegebenen .m3u Dateizeile geht durch. Sie gibt die aktuelle Zeile unbearbeitet zurück und setzt die Variable FLAG zurück, wenn die Variable FLAG gesetzt ist, was am Anfang nicht der Fall ist.

Dann sucht es nach #EXTINF. Wenn gefunden (z. B. #EXTINF:0,XYZ), wird die Zeichenfolge nach dem Komma (XYZ) mit der angegebenen Suchzeichenfolge verglichen. Bei Übereinstimmung wird die aktuelle Zeile ausgegeben und FLAG Variable wird jetzt gesetzt, um auch die folgende Zeile zu erhalten.

Die Kopfzeile #EXTM3U wird immer ausgegeben.

Das Umschalten delayed expansion macht dieses Skript robust gegenüber allen Zeichen, die eine besondere Bedeutung für den Befehlsinterpreter haben, ohne sie zu verlieren.

+0

Danke - Das scheint für eine Zeile zu funktionieren. Allerdings möchte ich diesen Befehl in eine andere Fledermaus-Datei einfügen und mehr als einen Kanal in verschiedene Dateien extrahieren ... Die Fledermaus-Datei wird nach dem ersten Kanal, den ich extrahiert habe, gerade beendet. – GDrago

+0

Was meinst du mit * mehr als 1 Kanal *? Willst du mehr als einen '#EXTINF:' Abschnitt extrahieren, oder meinst du mehr als eine Zeile nach einem einzelnen '#EXTINF:' Abschnitt? – aschipfl

+1

Tut mir leid, dass ich mich nicht gut erklären konnte ... Ich habe es geschafft, mit CALL vor extract-entry.bat darüber hinwegzukommen. Ich habe alle gut gearbeitet. Danke für Ihre Hilfe! – GDrago

1

Setzen Sie diesen Code in die Datei filter.cmd.

@echo off 
set INPUT=%1&set MATCH=%2& set MATCHED=0 
for /f "delims=" %%a in (%INPUT%) do call :line "%%~a" 
goto :eof 
:line 
set EXT=&TITLE=& 
for /f "tokens=1 delims=:" %%a in ("%~1") do set EXT=%%~a 
for /f "tokens=1,2,* delims=:," %%a in ("%~1") do set TITLE=%%~c 
if "%EXT%" == "#EXTM3U" echo %~1 
if "%EXT%" == "#EXTINF" (
    set MATCHED=0 
    echo %TITLE%| findstr /l %MATCH% >nul && set MATCHED=1 
) 
if %MATCHED%==1 echo %~1 

Anwendungsbeispiel:

filter.cmd input_file.m3u XYZ > output_file.m3u 

Hier ist eine Erklärung:
Jede Eingangsleitung geteilt wird unter Verwendung für/f mit Token und delims. MATCHED wird gesetzt, wenn die Zeile mit #EXTINF beginnt und der Rest die passende Zeichenfolge enthält (zweites Argument). Wenn MATCHED gesetzt ist, werden die Zeilen bis zum nächsten #EXTINF ausgegeben.

+0

1. Es ist nicht ganz effizient, jede Zeile zweimal mit 'for/F' zu analysieren, man könnte sie einfach kombinieren. 2. Sie sollten '% 1' durch'% ~1' ersetzen, gleiches gilt für '% 2'. 3. Die Syntax 'set 'VAR = Value'' ist sicherer gegen Sonderzeichen (z. B. wenn eine Zeichenfolge '& '?) Enthält. 4. Sie sollten '% MATCH%' zwischen '' '' in die 'findstr'-Befehlszeile setzen. 5.Ich empfehle, switch '/ X' zu' findstr' zu geben, damit der ganze Titel übereinstimmt und/oder '/ C', um einen literalen Suchstring zu definieren (beachten Sie, dass ohne'/C', Leerzeichen im Suchzeichenfolge bilden Worttrennzeichen). – aschipfl

+0

1. Ich habe nicht versucht, eine kugelsichere und minimale Lösung zu zeigen, wenn ich es getan hätte, hätte ich es sowieso in einer anderen Sprache gemacht. Der Punkt war, die Verwendung von for-Schleifen zu veranschaulichen. 2-4. Es ist nicht notwendig,% 1 zu% ~ 1, quote set =, MATCH, INPUT zu ersetzen, da sie von der Befehlszeile stammen, die bereits korrekt zitiert wurde. Und wenn jemand das Skript mit nicht angegebenen Parametern ausführt, die & enthalten, können Sie nichts dagegen tun. – wolfrevokcats

+0

Korrektes Zitieren ist * sehr * wichtig im Stapel: Wenn '% ~ 1' verwendet wird, werden Anführungszeichen entfernt, indem im Code"% ~ 1 "' angegeben wird. '% 1' wird auf das Argument erweitert,'% ~1' entfernt umgebende Anführungszeichen, so dass "% ~ 1" 'der sicherste Weg ist, in Anführungszeichen geschriebene Strings (' "% 1" 'könnte sogar zu over führen -Quote-Strings, wenn bereits in einer zitierten Art und Weise zur Verfügung gestellt); Zitate vermeiden Probleme mit Leerstellen (Token-Separatoren) und Sonderzeichen in den Strings; Ihre Antwort zeigt jedoch, wie 'for/F' funktioniert ... – aschipfl