2009-06-14 5 views
4

Welche Sprache sollte ich für die Manipulation von Dateien und Zeichenfolgen verwenden?Wie macht man das in PowerShell? Oder: Welche Sprache für die Manipulation von Dateien und Zeichenfolgen?

Dies scheint objektiv, aber wirklich nicht, denke ich. Es gibt viel zu sagen. Zum Beispiel kann ich klar sehen, dass Perl für die meisten Anwendungen ein offensichtlicherer Kandidat als Java wäre. Ich muss das ziemlich oft machen und zu diesem Zeitpunkt verwende ich C# dafür, aber ich hätte gerne eine eher skriptähnliche Sprache, um das zu tun.

Ich kann mir vorstellen, Perl wäre ein Kandidat dafür, aber ich möchte es in PowerShell tun, da PowerShell Zugriff auf die .NET-Bibliothek (einfach). Oder ist Python ein besserer Kandidat dafür? Wenn ich eine neue Sprache lernen muss, ist Python sicherlich einer auf meiner Liste, anstatt Perl.

Ich möchte zum Beispiel eine Datei lesen, einige Änderungen vornehmen und sie erneut speichern. ZB: öffne es, nummeriere alle Zeilen (zB mit 3 Ziffern) und schließe es. Jedes Beispiel in jeder Sprache wäre willkommen, aber je kürzer desto besser. Es ist Utility Scripting, ich bin hier, nicht OO, TDentwickelt, Unit-Test-Zeug natürlich.

Was würde ich sehr gerne sehen, etwas wie (pseudocode hier):

open foobar.as f 

foreach line in f.lines 
line.addBefore(currenIteratorCounter.format('ddd') + '. ') 

close f 

So:

bar.txt 

Frank Zappa 
Cowboy Henk 
Tom Waits 

numberLines bar.txt 

bar.txt 

001. Frank Zappa 
002. Cowboy Henk 
003. Tom Waits 

UPDATE:

Die Perl und Python Beispiele hier sind groß und definitiv in der Linie dessen, was ich erhofft und erwartet hatte. Aber gibt es da draußen keine PowerShell-Leute?

Antwort

11

Das in PowerShell eigentlich recht einfach:

function Number-Lines($name) { 
    Get-Content $name | ForEach-Object { $i = 1 } { "{0:000}. {1}" -f $i++,$_ } 
} 

Was ich hier mache ist immer den Inhalt der Datei, dies wird eine String[], über die ich mit ForEach-Object iterieren und eine Formatzeichenfolge mit dem Operator -f. Das Ergebnis wird einfach als anderes String[] aus der Pipeline entfernt, das bei Bedarf zu einer Datei umgeleitet werden kann.

Sie können es ein wenig durch die Verwendung Aliase verkürzen:

gc .\someFile.txt | %{$i=1}{ "{0:000}. {1}" -f $i++,$_ } 

aber ich werde das nicht für eine Funktionsdefinition empfehlen.

Sie möchten jedoch die Verwendung von zwei Durchgängen in Erwägung ziehen und die Formatzeichenfolge im laufenden Betrieb konstruieren, um eine größere Anzahl von Zeilen unterzubringen. Wenn es 1500 Zeilen {0:000} gibt, wird es nicht mehr ausreichen, um eine sauber ausgerichtete Ausgabe zu erhalten.

Wie für die Sprache ist am besten für solche Aufgaben, Sie auf Faktoren aussehen könnten wie

  • Prägnanz von Code (Perl schwer sein wird, es zu schlagen, vor allem, dass Einzeiler in einer anderen Antwort)
  • Lesbarkeit und Wartbarkeit des Codes
  • Verfügbarkeit der Werkzeuge (Perl und Python werden unter Windows standardmäßig installiert (Powershell nur seit Windows 7), so Einsatz behindert werden könnte.)

In Anbetracht des letzten Punktes könnte es sogar besser sein, cmd für diese Aufgabe zu verwenden. Der Code ist in ähnlicher Weise recht einfach:

@echo off 
setlocal 
set line=1 
for /f "delims=" %%l in (%1) do call :process %%l 
endlocal 
goto :eof 

:process 
call :lz %line% 
echo %lz%. %* 
set /a line+=1 
goto :eof 

:lz 
if %1 LSS 10 set lz=00%1&goto :eof 
if %1 LSS 100 set lz=0%1&goto :eof 
set lz=%1&goto :eof 
goto :eof 

Das setzt natürlich voraus, dass es irgendwo anders als die eigene Maschine zu laufen hat. Wenn nicht, dann verwenden, was Ihren Bedürfnissen entspricht :-)

+0

1. Ich habe viele Fensterumgebungen gesehen, in denen Perl installiert wurde, und nicht vom Benutzer des PCs, woher es kommt, weiß ich nicht.
2. Können Sie auch ein cmd Beispiel geben? – Peter

+3

Dies ist eine hervorragende Antwort (die ich bookmarken werde), aber wollte nur darauf hinweisen, dass Sie tatsächlich gezeigt haben, dass Powershell normalerweise die Antwort ist. Es macht so etwas so einfach, dass das Erstellen einer Funktion zum Einwickeln normalerweise Zeitverschwendung ist. Sie könnten einfach die Initialisierung von $ i inline setzen, um es zu einem Einzeiler zu machen. Es ist viel lesbarer als Perl. Und schließlich ist PowerShell ein Betriebssystem "update", das die Erlaubnis, es zu installieren, etwas einfacher macht. Bald wird es standardmäßig auf Windows-Betriebssystemen installiert, beginnend mit Windows 7, glaube ich. – Mike

+0

@Peter Perl würde von einem Administrator auf dem Computer installiert werden. Wie Mike sagte, PowerShell ist standardmäßig in Windows 7 und Server 2008 R2 installiert und aktiviert und ist über Windows Update oder WSUS als optionales Update für Vista, XP und Server 2003 verfügbar. Es ist eine Funktion auf Server 2008 –

1

Python

target = open("bar_with_numbers.txt", "w") 
source = open("bar.txt", "r") 
for count, line in enumerate(source): 
    target.write("%3d. %s\n" % (count+1, line)) 
source.close() 
target.close() 

Erstens ist es eine schlechte Politik "update" Dateien an seinem Platz. Auf lange Sicht wird dies zu einer bedauerlichen Entscheidung, da das Debugging durch den Verlust der Historie erschwert wird.

Wenn Sie Betriebssystemumleitungsfunktionen verwenden, kann dieses Programm vereinfacht werden.

import sys 
for count, line in enumerate(sys.stdin): 
    sys.stdout.write("%3d. %s\n" % (count+1, line)) 

Dann können Sie diese enumerate.py laufen als

python enumerate.py <bar.txt >bar_with_numbers.txt 

Noch wichtiger folgt, können Sie auch dies tun.

python enumerate.py <bar.txt | the_next_step 
+0

+1 wow, fantastisch, ich habe gerade meinen pseudolang hinzugefügt, und dein python macht das fast, tx. Soweit Ihre Bemerkung geht: natürlich, es ist für das Beispiel und ich verliere nie Geschichte tx Subversion. – Peter

+0

Zwischenergebnisse in Subversion zu halten ist kein Ersatz für ein gutes Pipeline-Design. Das Aktualisieren von Dateien an Ort und Stelle ist einfach ein schlechtes Design. Programme stürzen ab, verfälschen Dateien und machen das Zurückfallen komplexer als eine triviale Wiederholung. –

1

Definitiv Perl. Es unterstützt die Inline-Ersatz (unter Windows Sie das Skript mit Perl .i.bak beginnen muß (da Windows nicht diesen Inline tun kann, und erstellt eine BAK-Datei mit dem gleichen Namen.)

open(IN,'+>'.$yourfile) || die "Can not open file $yourfile: $!"; 

my $line_no = 1; 

while(<IN>){ 
    print "$line_no. $_"; 
    $line_no++; 
} 
close IN; 

-Code nur aus dem Speicher eingegeben ohne Prüfung. Aber sollte das funktionieren. Sie wollen wahrscheinlich eine gewisse Logik für die Formatierung von $ Line_No (zB erste Zählung Zeilen und fügen Sie dann so viel Nullstellen, wie Sie benötigen.) hinzufügen

2
perl -i -ne 'printf("00%d. %s",$.,$_)' your-filename-here 

Sie% 03d statt möchten .

+0

+1 Wenn ich das sehe, muss ich vielleicht perl ... funktioniert das auf Windows zu? siehe Bemerkung von SchlaWiener – Peter

+0

Es ist viele Jahre her, seit ich Perl auf Windows verwendet habe, also werde ich auf SchlaWieners Vorschlag von -i.bak verzichten. Sicherlich kann es nicht schaden und eine Sicherungskopie ist immer gut. –

+1

+1, aber Sie brauchen nicht einmal '$ _ =' Teil. –

1

Auf einem Debian-System (und wahrscheinlich auch andere Linux-Distributionen), könnten Sie dies tun:

$ nl -w 3 -n rz -s ". " [filename] > [newfilename] 
+0

Machen Sie nicht den Gegenwert von " Katzendatei> Datei ". Sie werden wahrscheinlich alle Ihre Daten verlieren, abhängig davon, in welcher Reihenfolge die Shell und das aufgerufene Programm Dinge tun. –

+0

danke für den Vorschlag, mein Beispiel geändert. – ylebre

2

Es ist nicht das, was Sie wollen, aber bitte erinnern findstr.exe (und find.exe) zu Zeiten ...

findstr/n“. * "filename find" "/ v/n filename

+0

+ Ich möchte mir etwas Zeit nehmen, um einige Einsichten zu einer alten und bereits akzeptierten Frage hinzuzufügen. – Peter

Verwandte Themen