Προγραμματισμός

split Command για DOS / Windows Via Groovy

Μία από τις εντολές που μου λείπουν περισσότερο από το Linux όταν εργάζομαι σε περιβάλλοντα Windows / DOS είναι η εντολή split. Αυτή η εξαιρετικά εύχρηστη εντολή επιτρέπει σε κάποιον να διαχωρίσει ένα μεγάλο αρχείο σε πολλά μικρότερα αρχεία που καθορίζονται από τον καθορισμό είτε από τον αριθμό γραμμών είτε από τον αριθμό των byte (ή kilobytes ή megabytes) που είναι επιθυμητά για τα μικρότερα αρχεία. Υπάρχουν πολλές χρήσεις για τέτοια λειτουργικότητα, όπως η τοποθέτηση αρχείων σε συγκεκριμένα μέσα, η δημιουργία αρχείων "αναγνώσιμων" από εφαρμογές με περιορισμούς μήκους αρχείων και ούτω καθεξής. Δυστυχώς, δεν γνωρίζω ένα ισοδύναμο split για Windows ή DOS. Το PowerShell μπορεί να είναι σενάριο για να κάνει κάτι τέτοιο, αλλά αυτή η εφαρμογή είναι συγκεκριμένη για το PowerShell. Υπάρχουν επίσης διαθέσιμα προϊόντα τρίτων με παρόμοια λειτουργικότητα. Ωστόσο, αυτές οι υπάρχουσες λύσεις αφήνουν αρκετό για να είναι επιθυμητό ότι έχω το κίνητρο να εφαρμόσω ένα ισοδύναμο split στο Groovy και αυτό είναι το αντικείμενο αυτής της ανάρτησης. Επειδή το Groovy εκτελείται στο JVM, αυτή η εφαρμογή θα μπορούσε θεωρητικά να εκτελεστεί σε οποιοδήποτε λειτουργικό σύστημα με μια σύγχρονη εφαρμογή Java Virtual Machine.

Για να δοκιμάσετε και να δείξετε το σενάριο split που βασίζεται στο Groovy, απαιτείται κάποιος τύπος αρχείου προέλευσης. Θα χρησιμοποιήσω το Groovy για να δημιουργήσω εύκολα αυτό το αρχείο προέλευσης. Το ακόλουθο απλό σενάριο Groovy, buildFileToSplit.groovy, δημιουργεί ένα απλό αρχείο κειμένου που μπορεί να χωριστεί.

#! / usr / bin / env groovy // // buildFileToSplit.groovy // // Δέχεται ένα όρισμα για τον αριθμό γραμμών που θα γραφτούν στο παραγόμενο αρχείο. // Εάν δεν έχει καθοριστεί αριθμός γραμμών, χρησιμοποιεί προεπιλογή 100.000 γραμμών. // if (! args) {println "\ n \ nΧρήση: buildFileToSplit.groovy fileName lineCount \ n" println "όπου το όνομα_αρχείου είναι το όνομα του αρχείου που θα δημιουργηθεί και το lineCount είναι ο αριθμός" println "των γραμμών που θα τοποθετηθούν στο παραγόμενο αρχείο." System.exit (-1)} fileName = args [0] numberOfLines = args.length> 1; args [1] ως Integer: 100000 file = new File (fileName) // διαγράφει το αρχείο εξόδου εάν υπήρχε ήδη file.delete () 1.upto (numberOfLines, {file << "This is line # $ {it}. \ ν "}) 

Αυτό το απλό σενάριο χρησιμοποιεί τη σιωπηρά διαθέσιμη λαβή "args" του Groovy για πρόσβαση σε ορίσματα γραμμής εντολών για το σενάριο buildFileToSplit.groovy. Στη συνέχεια, δημιουργεί ένα ενιαίο αρχείο μεγέθους με βάση το όρισμα του αριθμού γραμμών που παρέχονται. Κάθε γραμμή είναι σε μεγάλο βαθμό μη γνήσια και δηλώνει "Αυτή είναι η γραμμή #" ακολουθούμενη από τον αριθμό γραμμής. Δεν είναι ένα φανταστικό αρχείο προέλευσης, αλλά λειτουργεί για το παράδειγμα διαχωρισμού. Το επόμενο στιγμιότυπο οθόνης δείχνει την εκτέλεση και την έξοδο του.

Το παραγόμενο αρχείο source.txt μοιάζει με αυτό (εμφανίζεται μόνο η αρχή και το τέλος του εδώ):

Αυτή είναι η γραμμή # 1. Αυτή είναι η γραμμή # 2. Αυτή είναι η γραμμή # 3. Αυτή είναι η γραμμή # 4. Αυτή είναι η γραμμή # 5. Αυτή είναι η γραμμή # 6. Αυτή είναι η γραμμή # 7. Αυτή είναι η γραμμή # 8. Αυτή είναι η γραμμή # 9. Αυτή είναι η γραμμή # 10. . . . Αυτή είναι η γραμμή # 239. Αυτή είναι η γραμμή # 240. Αυτή είναι η γραμμή # 241. Αυτή είναι η γραμμή # 242. Αυτή είναι η γραμμή # 243. Αυτή είναι η γραμμή # 244. Αυτή είναι η γραμμή # 245. Αυτή είναι η γραμμή # 246. Αυτή είναι η γραμμή # 247. Αυτή είναι η γραμμή # 248. Αυτή είναι η γραμμή # 249. Αυτή είναι η γραμμή # 250. 

Υπάρχει τώρα ένα αρχείο προέλευσης διαθέσιμο για διαχωρισμό. Αυτό το σενάριο είναι πολύ μεγαλύτερο επειδή το έκανα να ελέγξει για περισσότερες συνθήκες σφάλματος, επειδή πρέπει να χειριστεί περισσότερες παραμέτρους γραμμής εντολών και απλώς επειδή κάνει περισσότερα από το σενάριο που δημιούργησε το αρχείο προέλευσης. Στη συνέχεια εμφανίζεται το σενάριο, που ονομάζεται split.groovy:

#! / usr / bin / env groovy // // split.groovy // // Διαχωρίστε ένα αρχείο σε πολλά αρχεία παρόμοια με τον τρόπο λειτουργίας της εντολής Unix / Linux split //. Αυτή η έκδοση του σεναρίου προορίζεται μόνο για αρχεία κειμένου. // // Αυτό το σενάριο διαφέρει από την παραλλαγή Linux / Unix με συγκεκριμένους τρόπους. Για // παράδειγμα, τα μηνύματα εξόδου αυτού του σεναρίου διαφέρουν σε αρκετές περιπτώσεις και αυτό το // σενάριο απαιτεί το όνομα του αρχείου που διαιρείται να παρέχεται ως όρισμα // γραμμής εντολών και όχι να παρέχει την επιλογή να το παρέχει ως // τυπική είσοδος . Αυτό το σενάριο παρέχει επίσης μια επιλογή "-v" ("--version") που δεν // διαφημίζεται για την έκδοση Linux / Unix. // // ΠΡΟΣΟΧΗ: Αυτό το σενάριο προορίζεται μόνο ως απεικόνιση της χρήσης του Groovy για // προσομοίωση της εντολής σεναρίου Unix / Linux. Δεν προορίζεται για παραγωγή // χρήση ως έχει. Αυτό το σενάριο έχει σχεδιαστεί για να δημιουργεί αντίγραφα ασφαλείας των αρχείων που δημιουργούνται // από τη διάσπαση ενός αρχείου πηγής, αλλά μόνο μία εφεδρική έκδοση // δημιουργείται και παρακάμπτεται από τυχόν περαιτέρω αιτήματα. // // //marxsoftware.blogspot.com/ // import java.text.NumberFormat NEW_LINE = System.getProperty ("line.separator") // // Χρησιμοποιήστε το Groovy's CliBuilder για την επεξεργασία ορίσματος γραμμής εντολών // def cli = νέο CliBuilder (χρήση: 'split [OPTION] [INPUT [PREFIX]]') cli.with {h (longOpt: 'help', 'Usage Information') a (longOpt: 'suffix-length', type: Number, ' Χρησιμοποιήστε επιθήματα μήκους N (η προεπιλογή είναι 2) ', args: 1) b (longOpt:' bytes ', type: Number,' Μέγεθος κάθε αρχείου εξόδου σε bytes ', args: 1) l (longOpt:' lines ', τύπος: Αριθμός, "Αριθμός γραμμών ανά αρχείο εξόδου", args: 1) t (longOpt: "verbose", "Print diagnostic to standard error πριν από το άνοιγμα κάθε αρχείου εξόδου", args: 0) v (longOpt: 'version ',' Έκδοση εξόδου και έξοδος ', args: 0)} def opt = cli.parse (args) if (! Opt || opt.h) {cli.usage (); return} if (opt.v) {println "Έκδοση 0.1 (Ιούλιος 2010)"; return} if (! opt.b &&! opt.l) {println "Καθορίστε το μήκος των διαχωρισμένων αρχείων με τον αριθμό των bytes ή τον αριθμό των γραμμών" cli.usage () return} if (opt.a &&! opt.a. isNumber ()) {println "Το μήκος του επιθήματος πρέπει να είναι αριθμός"; cli.usage (); return} if (opt.b &&! opt.b.isNumber ()) {println "Το μέγεθος των αρχείων σε byte πρέπει να είναι αριθμός"; cli.usage (); return} if (opt.l &&! opt.l.isNumber ()) {println "Ο αριθμός γραμμών πρέπει να είναι αριθμός"; cli.usage (); return} // // Προσδιορίστε αν τα διαχωρισμένα αρχεία θα έχουν μέγεθος ανά αριθμό γραμμών ή αριθμό bytes // ιδιωτικό enum LINES_OR_BYTES_ENUM {BYTES, LINES} bytesOrLines = LINES_OR_BYTES_ENUM.LINES defixLength = opt.a? opt.a.toBigInteger (): 2 if (επίθημαΜήκος 1? opt.arguments () [1]: "x" try {file = new File (όνομα αρχείου) εάν (! file.exists ()) {println "Αρχείο προέλευσης $ Το {filename} δεν είναι έγκυρο αρχείο προέλευσης. "System.exit (-4)} int fileCounter = 1 firstFileName =" $ {prefix} $ {fileSuffixFormat.format (0)} "if (verboseMode) {System.err.println "Δημιουργία αρχείου $ {firstFileName} ..."} outFile = createFile (firstFileName) if (bytesOrLines == LINES_OR_BYTES_ENUM.BYTES) {int byteCounter = 0 file.eachByte {if (byteCounter <numberBytes) {outFile << νέα συμβολοσειρά )} άλλο {nextOutputFileName = "$ {prefix} $ {fileSuffixFormat.format (fileCounter)}" if (verboseMode) {System.err.println "Δημιουργία αρχείου $ {nextOutputFileName} ..."} outFile = createFile (nextOutputFileName) outFile << new String (it) fileCounter ++ byteCounter = 0} byteCounter ++}} other {int lineCounter = 0 file.eachLine {if (lineCounter <numberLines) {outFile << it << NEW_LINE} άλλο {nextOutputFileName = "$ {πρόθεμα} $ {fileSuffixFormat.format (fileCounter)} " if (verboseMode) {System.err.println "Δημιουργία αρχείου $ {nextOutputFileName} ..."} outFile = createFile (nextOutputFileName) outFile << it << NEW_LINE fileCounter ++ lineCounter = 0} lineCounter ++}}} catch (FileNotFoundException fnfEx) println System.properties println "$ {fileName} δεν είναι έγκυρο αρχείο προέλευσης: $ {fnfEx.toString ()}" System.exit (-3)} catch (NullPointerException npe) {println "NullPointerException αντιμετώπισε: $ {npe.toString ()} "System.exit (-4)} / ** * Δημιουργήστε ένα αρχείο με το παρεχόμενο όνομα αρχείου. * * @param fileName Όνομα αρχείου που θα δημιουργηθεί. * Το αρχείο @return δημιουργήθηκε με το παρεχόμενο όνομα. null εάν το όνομα που παρέχεται είναι null ή * κενό. * / def File createFile (String fileName) {if (! fileName) {println "Δεν είναι δυνατή η δημιουργία αρχείου από μηδενικό ή κενό όνομα αρχείου." return null} outFile = νέο αρχείο (όνομα_αρχείου) εάν (outFile.exists ()) {outFile.renameTo (νέο αρχείο (όνομα_αρχείου + ".bak")) outFile = νέο αρχείο (όνομα_αρχείου)} επιστροφή 

Αυτό το σενάριο θα μπορούσε να βελτιστοποιηθεί και να τροποποιηθεί καλύτερα, αλλά εκπληρώνει το σκοπό του να δείξει πώς ο Groovy παρέχει μια ωραία προσέγγιση για την εφαρμογή σεναρίων ανεξάρτητων πλατφορμών.

Το επόμενο στιγμιότυπο οθόνης δείχνει τη χρήση της ενσωματωμένης υποστήριξης CLI του Groovy από το σενάριο.

Τα επόμενα δύο στιγμιότυπα οθόνης δείχνουν τη διάσπαση του αρχείου προέλευσης σε μικρότερα αρχεία με αριθμούς γραμμής και bytes αντίστοιχα (και χρησιμοποιώντας διαφορετικές επιλογές επιθήματος και ονόματος αρχείου). Η πρώτη εικόνα δείχνει ότι δημιουργούνται τρία αρχεία εξόδου όταν χωρίζονται σε 100 γραμμές (250 γραμμές στο αρχείο προέλευσης). Η επιλογή -α καθορίζει ότι τέσσερα ακέραια μέρη θα βρίσκονται στο όνομα αρχείου. Σε αντίθεση με το Linux split, αυτό το σενάριο δεν εγγυάται ότι ο αριθμός ακεραίων που παρέχονται από τον χρήστη είναι επαρκής για να καλύψει τον αριθμό των απαραίτητων αρχείων εξόδου.

Η δεύτερη εικόνα (επόμενη εικόνα) δείχνει το σενάριο που χωρίζει το αρχείο προέλευσης με βάση τον αριθμό των byte και χρησιμοποιεί διαφορετικό όνομα αρχείου και μόνο δύο ακέραιους αριθμούς για την αρίθμηση.

Όπως αναφέρθηκε παραπάνω, αυτό το σενάριο είναι "τραχύ κομμάτι". Θα μπορούσε να βελτιωθεί από την άποψη του ίδιου του κώδικα καθώς και από πλευράς λειτουργικότητας (επεκτείνεται σε καλύτερη υποστήριξη δυαδικών μορφών και για να βεβαιωθείτε ότι τα επιθήματα ονόματος αρχείου είναι αρκετά μεγάλα για τον αριθμό των αρχείων εξόδου). Ωστόσο, το σενάριο εδώ δείχνει μια από τις αγαπημένες μου χρήσεις του Groovy: να γράφω σενάρια ανεξάρτητα από την πλατφόρμα χρησιμοποιώντας γνωστές βιβλιοθήκες Java και Groovy (SDK και GDK).

Αυτή η ιστορία, "split Command για DOS / Windows Via Groovy" δημοσιεύθηκε αρχικά από την JavaWorld.

$config[zx-auto] not found$config[zx-overlay] not found