एक निष्पादन योग्य स्क्रिप्ट फ़ाइल जो POSIX और Windows पर चलती है


16

चुनौती : एक एकल स्क्रिप्ट फ़ाइल लिखें, foo.cmdजिसे वनीला विंडोज cmd.exeप्रॉम्प्ट (पावरस्हेल नहीं, प्रशासक मोड में नहीं) से प्राप्त किया जा सकता है , मनमाने ढंग से विंडोज-विशिष्ट कोड निष्पादित करने के लिए ...

> .\foo.cmd
Hello Windows! 

... लेकिन यह भी एक विशिष्ट POSIX अनुरूप (लिनक्स / OSX) से अनछुए शैल लागू किया जा शीघ्र ( bash, tcsh, या zsh), मनमाने ढंग से POSIX-विशिष्ट कोड निष्पादित करने के लिए:

$ chmod a+x foo.cmd
$ ./foo.cmd
Hello POSIX!

... तृतीय-पक्ष दुभाषियों / उपकरणों की स्थापना या निर्माण की आवश्यकता के बिना।

मुझे पता है कि यह संभव है, लेकिन cruft के साथ (यानी विंडोज पर, कचरा / त्रुटि-संदेश की एक या दो पंक्तियाँ "हैलो विंडोज!" से पहले stderr या stdout में प्रिंट की जाती हैं)।

जीतने की कसौटी न्यूनतम (पहले) cruft लाइनों की संख्या है, और (दूसरे) cruft वर्णों की संख्या।

Cruft को किसी भी कंसोल आउटपुट (stdout या stderr) के रूप में परिभाषित किया जा सकता है जो कि (मनमाना) पेलोड कोड द्वारा निर्मित नहीं है। ब्लैंक लाइनों को लाइन काउंट में गिना जाता है। कैरेक्टर काउंट में न्यूलाइन्स की गिनती नहीं की जाती है। Cruft स्कोर दोनों प्लेटफार्मों भर में अभिव्यक्त किया जाना चाहिए। चलो इस तरह के तंत्र की अवहेलना करते हैं clsजो क्रुफ्ट को दूर करते हैं लेकिन पिछले टर्मिनल आउटपुट को खाली करने की लागत पर भी। यदि विंडोज़ आपके आदेशों को इको कर देता है क्योंकि आपने @echo offअभी तक चालू नहीं किया है, तो चलिए उन पात्रों को छोड़ दें जिन्हें यह वर्तमान निर्देशिका और शीघ्रता को प्रिंट करने में खर्च करता है।

एक माध्यमिक मानदंड अंदर की समाधान की सादगी / लालित्य है foo.cmd: यदि "अवसंरचना" को किसी भी चरित्र के रूप में परिभाषित किया गया है जो सीधे मनमाने ढंग से पेलोड कोड में शामिल नहीं है, तो पहले लाइनों की संख्या कम से कम करें जिसमें अवसंरचना वर्ण शामिल हैं, और बुनियादी ढांचे की कुल संख्या दूसरी है। पात्र।

यदि CRLF लाइन-एंडिंग वाली फ़ाइल के बावजूद POSIX भाग काम करेगा तो अतिरिक्त यश! (यह निश्चित नहीं है कि अंतिम भाग भी संभव है।)

मेरा मौजूदा समाधान, जिसे मैं यहां पोस्ट करूंगा, जब दूसरों के पास मौका होगा, तो इन्फ्रास्ट्रक्चर कोड की 6 पंक्तियों का उपयोग करता है (नई वर्णमाला को छोड़कर 52 वर्ण)। यह क्रुफ़्ट की 5 पंक्तियों का उत्पादन करता है, जिनमें से दो रिक्त हैं, जिनमें से सभी विंडोज पर होते हैं (30 वर्णों को छोड़कर नई पंक्ति और वर्तमान निर्देशिका / शीघ्र स्ट्रिंग को छोड़कर जो उन दो पंक्तियों में दिखाई देती है)।


है , फिर एक खोल / बैच स्क्रिप्ट होने के लिए?
बिल्ली

1
क्या किसी को डॉस के लिए कोशिश-ऑनलाइन वातावरण का पता है?
डिजिटल ट्रॉमा

1
मैंने पाया यह एक है, लेकिन यह नहीं करता है मुझे दर्ज ":", "\", "{" या "}" वर्ण: - /
डिजिटल ट्रामा

@DigitalTrauma में शराब है (जो आपको स्थापित करना चाहिए था, यदि आप नहीं करते हैं, क्योंकि यह काम है)
बिल्ली

1
@ कोट धन्यवाद - मेरा जवाब अब शराब के तहत काम करने लगता है।
डिजिटल ट्रामा

जवाबों:


15

0 cruft लाइनें, 0 cruft chars, 2 infra। लाइनें, 21 इन्फ्रा। chars, CRLF ठीक है

:<<@goto:eof
@echo Hello Windows!
@goto:eof
echo "Hello POSIX!" #

दूसरे उपाय निकाले।

exit /bडिजिटल ट्रॉमा के उत्तर से 17 वर्ण

:<<@exit/b
@echo Hello Windows!
@exit/b
echo "Hello POSIX!" #

प्रबल दावेदार! विशेष रूप से दूसरा संस्करण (सादगी / लालित्य मानदंड पर, यह बहुत अच्छा है कि पेलोड लाइनों को जिस तरह से पहले संस्करण में किया जाता है, उससे अधिक नहीं होना चाहिए)। यह विंडोज और OSX पर मेरे लिए चलता है। शुरू में मुझे यह कहते हुए कि : command not foundजब भी कोई खाली लाइन पॉज़िक्स पेलोड में आती है, तो मुझे :एक लाइन मिलती है , लेकिन मुझे अंत में पता चला कि यह पहली लाइन के बारे में नहीं थी, बल्कि CRLFs द्वारा असुरक्षित थी #। यह मेरे लिए खबर थी कि एक #!लाइन की जरूरत नहीं है - जो कि मेरे पिछले संस्करण में विंडोज क्रुफ्ट की दो लाइनों के लिए जिम्मेदार थी।
jez

पहले संस्करण को स्कोर के बाद से करने के लिए यह शायद पात्रों कहते हैं कठिन है : ` >&3` \ करने के लिए हर पेलोड की लाइन, मैं आप कह सकते हैं अपने बुनियादी ढांचे लागत मनमाने ढंग से अधिक है लगता है।
jez

@ जेज आप उत्तरों के लिए एक संख्यात्मक अंक की गणना कर रहे हैं? यदि हां, तो आपको यह सवाल करने की ज़रूरत है कि यह कैसे किया जाए।
डिजिटल ट्रामा

मैं कोडगोल्फ के लिए नया हूं, इसलिए टीबीएच मुझे लगा कि मैं था उम्मीद है किसी तरह उत्तर देने की उम्मीद । फिर भी मुझे लगता है कि यह सवाल स्पष्ट करता है: पहला, cruft लाइनों की संख्या; cruft वर्णों की संख्या से उस पर संबंध तोड़ना; इसके बाद इन्फ्रास्ट्रक्चर लाइनों की संख्या, फिर इन्फ्रास्ट्रक्चर कैरेक्टर्स की संख्या। मुझे ऐसे समाधानों की उम्मीद नहीं थी जो पेलोड लाइनों को पिघला दें, जैसे जिमी का पहला समाधान। मैं यह स्पष्ट करने के लिए प्रश्न को थोड़ा बदल दूंगा कि यह अवांछनीय है (उस मामूली गोलपोस्ट बदलाव के लिए खेद है, लेकिन मुझे नहीं लगता कि यह उसके दूसरे समाधान या आपके किसी भी संस्करण को अब तक प्रभावित करता है)
jez

ऐसा लगता है कि हमारे उत्तर परिवर्तित हो रहे हैं ;-) आपके पास स्कोरिंग में बढ़त है, हालांकि हेरेडोक उपयोग के साथ। क्या अंतिम #आवश्यक है?
डिजिटल ट्रॉमा

4

स्कोर 0 cruft + 4 इन्फ्रा लाइन + 32 इन्फ्रा चार्ट। LF और CRLF ठीक है।

यह इस ब्लॉग पर पाया गया है कि एमिगा बिट्स और अन्य अनावश्यक लाइनों के साथ बाहर आधारित है। मैंने DOS लाइनों को टिप्पणी उद्धरणों में छिपाया बजाय \लाइन का उपयोग करने के जारी है, ताकि यह CRLF और LF दोनों के साथ काम कर सके।

@REM ()(:) #
@REM "
@ECHO Hello Windows!
@EXIT /B
@REM "
echo Hello POSIX!

DOS CRLF या * nix LF लाइन एंडिंग के साथ, यह उबंटू, OSX और वाइन पर काम करता है:

ubuntu@ubuntu:~$ ./dosix.bat
Hello POSIX!
ubuntu@ubuntu:~$ wine cmd.exe
Wine CMD Version 5.1.2600 (1.6.2)

Z:\home\ubuntu>dosix.bat
Hello Windows!

Z:\home\ubuntu>exit
ubuntu@ubuntu:~$ 

इसे बनाने के लिए (CRLFs के साथ) एक * nix मशीन (OSX सहित) पर, एक टर्मिनल पर निम्नलिखित पेस्ट करें:

[ $(uname) = Darwin ] && decode=-D || decode=-d
ubuntu@ubuntu:~$ base64 $decode > dosix.bat << EOF
QFJFTSAoKSg6KSAjDQpAUkVNICINCkBFQ0hPIEhlbGxvIFdpbmRvd3MhDQpARVhJVCAvQg0KQFJF
TSAiDQplY2hvIEhlbGxvIFBPU0lYIQ0K
EOF

अच्छा लगता है! dosixएक अच्छा नाम भी है। लेकिन मेरे मैक (OS 10.9.4, डार्विन कर्नेल संस्करण 13.3.0, GNU बैश संस्करण 3.2.51) पर यह साथ चलने में विफल रहता है: ./dosix.cmd: line 13: syntax error: unexpected end of file कोई विचार क्यों?
jez

@Jz सुनिश्चित करें कि आप UTF-8 के साथ एन्कोडेड फाइल को सेव करें और विंडोज लाइन एंडिंग को संरक्षित करें!
बिल्ली

आह, यह इसलिए हो रहा था क्योंकि मेरे पास अनजाने में विंडोज लाइन-एंडिंग था और पहले संस्करण का उपयोग कर रहा था।
jez

ध्यान दें कि आप Bash में CR वर्ण इनपुट (या Cv) द्वारा दर्ज कर सकते हैं, दर्ज कर सकते हैं (या Cm)।
jimmy23013

@ जेजे तो यह स्कोर 0 cruft लाइन्स + 4 इन्फ्रास्ट्रक्चर लाइन्स + 32 इन्फ्रास्ट्रक्चर चार के रूप में है। तुलना के लिए एक अंक बनाने के लिए क्या इन नंबरों को किसी सार्थक तरीके से जोड़ा जाना चाहिए?
डिजिटल ट्रामा

2

मैं पहले से ही मेरे द्वारा उपयोग किए जा रहे समाधान को पोस्ट कर दूंगा, क्योंकि यह पहले से ही पिट चुका है। यह मेरे एक सहयोगी के सौजन्य से है जो मुझे लगता है कि डिजिटल ट्रॉमा के समान ब्लॉग प्रविष्टि को पढ़ा होगा ।

#!/bin/sh # >NUL 2>&1
echo \
@goto c \
>/dev/null
echo "Hello Posix!"
exit
:c
@echo Hello Windows!
  • Windows cruft: 5 लाइनें (जिनमें से दो खाली हैं) / 30 वर्ण
  • OSX cruft: 0
  • इन्फ्रास्ट्रक्चर: 6 लाइनें / 52 वर्ण
  • CRLF संगतता: केवल अगर #!लाइन पर नामित दुभाषिया परवाह नहीं करता है (तो मानक व्याख्याकारों जैसे shऔर दोस्तों के लिए, यह विफल रहता है)

POSIX पर एक स्क्रिप्ट हमेशा से शुरू होती है #!, जिसका मतलब है कि आपका एक ही जवाब है अब तक POSIX सिस्टम पर एक वैध स्क्रिप्ट है। यकीन है कि दूसरों में से कुछ चला सकते हैं - लेकिन केवल अगर वे एक खोल से शुरू कर रहे हैं दोषपूर्ण लिपियों के लिए समाधान के साथ।
कैसपर्ड

जानकार अच्छा लगा! मुझे लगता है कि मैं POSIX अनुपालन के लिए सख्त मानदंडों पर फजी हूं। मेरा वास्तविक लक्ष्य उन स्क्रिप्ट फ़ाइलों को रखना है जो "सबसे अधिक" आधुनिक डेस्कटॉप सिस्टम पर "बॉक्स से बाहर" काम करती हैं, जो भी इसका मतलब है - विंडोज 7/8/10, उबंटू, ओएसएक्स ... शेबलेस लिपियों के लिए कितना सार्वभौमिक है, मैं सोचता हूं? वैसे भी, मैं खुद को अंक देने के लिए नहीं जा रहा हूँ :-)
jez

मैंने ध्यान नहीं दिया कि उत्तर और प्रश्न दोनों एक ही व्यक्ति द्वारा लिखे गए थे। मुझे लगता है कि मेरे द्वारा काम किए गए सभी गोले एक लापता #!रेखा के लिए एक वर्कअराउंड है , लेकिन वे स्क्रिप्ट की व्याख्या करने के लिए अलग-अलग गोले का उपयोग करेंगे। इसका मतलब है कि एक "स्क्रिप्ट" जिसके साथ शुरू नहीं होता है #!उसे न केवल एक शेल में मान्य होना चाहिए, बल्कि हर शेल जो इसे संभवतः द्वारा व्याख्या किया जा सकता है। लेकिन इससे भी बदतर, यह केवल तभी काम करता है जब दूसरे शेल से शुरू किया जाता है। इस तरह की स्क्रिप्ट कमांड लाइन से काम कर सकती है, लेकिन उस संदर्भ में नहीं जहां आप इसे इस्तेमाल करने का इरादा रखते हैं।
केस्परड

धन्यवाद, यह बहुत ही शैक्षिक सामग्री है और इस चुनौती को शुरू करने से मुझे सीखने की उम्मीद थी। उन मामलों के लिए जहां यह (या हो सकता है) मायने रखता है, #!मेरे संपादित उत्तर में लाइन (21 वर्णों के साथ 1 बुनियादी ढांचा लाइन) को किसी और के जवाब के साथ जोड़कर विंडोज की केवल 2 पंक्तियों की लागत (जिसमें से एक रिक्त हो) या 23 चरस।
jez डेस

2

उत्तर और चर्चा का सारांश / संश्लेषण

यह मजेदार था, और मैंने बहुत कुछ सीखा।

कुछ Windows- विशिष्ट cruft अपरिहार्य है अगर, आपके POSIX सिस्टम पर, आपको अपनी स्क्रिप्ट को एक #!पंक्ति के साथ शुरू करने की आवश्यकता है । यदि आपके पास ऐसा करने के अलावा कोई विकल्प नहीं है, तो यह पंक्ति है:

#!/bin/sh # 2>NUL

शायद यह सबसे अच्छा मिल सकता है। यह Windows कंसोल पर आउटपुट के लिए एक रिक्त रेखा और cruft की एक पंक्ति का कारण बनता है। हालांकि, आप एक पंक्ति के बिना दूर होने में सक्षम हो सकते हैं #!: अधिकांश प्रणालियों पर, सामान्य शेल दुभाषियों में से एक स्क्रिप्ट निष्पादित करने में समाप्त हो जाएगा (समस्या यह है कि यह सार्वभौमिक रूप से अनुमानित नहीं है कि कौन सा दुभाषिया होगा - यह निर्भर करता है, लेकिन जरूरी नहीं कि आप कमांड को लागू करने के लिए उपयोग किए जाने वाले शेल के समान हों)।

उस मुश्किल पहली लाइन से परे, वहाँ वास्तव में कुछ सरल cruftless समाधान थे। Jimmy23013 द्वारा जीतने वाली प्रस्तुति में केवल दो छोटी अवसंरचना लाइनें शामिल थीं, और :दोनों प्लेटफार्मों पर "मूक" लाइन को लागू करने के लिए चरित्र की दोहरी भूमिका का उपयोग किया और एक दोस्त के रूप में एक वास्तविक तथ्य के रूप में shऔर एक लेबल के रूप में मार्कर में cmd.exe):

:<<@exit/b

:: Arbitrary Windows code goes here

@exit/b
#
# Arbitrary POSIX code goes here 

यह है भी CRLF लाइन अंत के बावजूद POSIX सिस्टम पर इस तरह के एक स्क्रिप्ट को चलाने के लिए, लेकिन सबसे दुभाषिए आप समाप्त करने के लिए है के लिए ऐसा करना संभव हर एक टिप्पणी या टिप्पणी चरित्र के साथ अपने POSIX खंड की लाइन (यहां तक कि खाली लाइनें)।

अंत में, यहां एक समाधान पर दो वेरिएंट हैं जो मैंने हर किसी के इनपुट के आधार पर विकसित किए हैं। वे लगभग सभी दुनिया में सबसे अच्छे हो सकते हैं, इसमें वे कमी से होने वाली क्षति को कम करते हैं #!और CRLF- अनुकूलता को भी स्मूथ बनाते हैं। दो अतिरिक्त बुनियादी ढांचा लाइनों की जरूरत है। अप्रत्याशित POSIX शेल द्वारा केवल एक (मानकीकृत) लाइन की व्याख्या की जानी है, और यह लाइन आपको बाकी स्क्रिप्ट ( bashनिम्नलिखित उदाहरण में) के लिए शेल का चयन करने की अनुमति देती है :

:<<@GOTO:Z

@echo Hello Windows!

@GOTO:Z
bash "$@"<<:Z
#
echo "Hello POSIX!" #
ps # let's throw this into the payload to keep track of which shell is being used
#
:Z

इन वंशानुगत समाधानों की सुंदरता का एक हिस्सा यह है कि वे अभी भी CRLF- मजबूत हैं: जब तक लाइन <<:Zके अंत में आते हैं, तब तक हेरेडोक प्रोसेसर वास्तव में खोज रहे होंगे, और पाएंगे, टोकन:Z\r

अंतिम मोड़ के रूप में, आप उन pesky एंड-ऑफ-लाइन टिप्पणियों से छुटकारा पा सकते हैं और अभी भी सीआरएलएफ-मजबूती को बनाए रख सकते हैं, \rअक्षरों को खोल से गुजरने से पहले बाहर निकाल कर। यह अप्रत्याशित खोल में थोड़ा अधिक विश्वास रखता है (इसके { tr -d \\r|bash;}बजाय इसका उपयोग करना अच्छा होगा (tr -d \\r|bash)लेकिन घुंघराले ब्रैकेट केवल बैश-सिंटैक्स हैं):

:<<@GOTO:Z

@echo Hello Windows!

@GOTO:Z
(tr -d \\r|bash "$@")<<:Z

echo "Hello POSIX!"
ps

:Z

बेशक, यह दृष्टिकोण स्क्रिप्ट में स्टड इनपुट को पाइप करने की क्षमता का त्याग करता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.