अगर बिना उपशमन के कई स्थितियां नहीं हैं तो?


23

मैं एक शेल में कई शर्तों को संयोजित करना चाहता हूं यदि कथन, और संयोजन को नकार दें। शर्तों के एक साधारण संयोजन के लिए मेरे पास निम्नलिखित कार्य कोड है:

if [ -f file1 ] && [ -f file2 ] && [ -f file3 ] ; then
  # do stuff with the files
fi

यह ठीक काम करता है। अगर मैं इसे नकारना चाहता हूं, तो मैं निम्नलिखित कार्य कोड का उपयोग कर सकता हूं:

if ! ( [ -f file1 ] && [ -f file2 ] && [ -f file3 ] ) ; then
  echo "Error: You done goofed."
  exit 1
fi
# do stuff with the files

यह भी उम्मीद के मुताबिक काम करता है। हालांकि, यह मेरे लिए होता है कि मुझे नहीं पता कि वास्तव में कोष्ठक वास्तव में क्या कर रहे हैं। मैं उन्हें केवल समूह बनाने के लिए उपयोग करना चाहता हूं , लेकिन क्या यह वास्तव में एक उपधारा पैदा कर रहा है? (मैं कैसे बता सकता हूं?) यदि ऐसा है, तो क्या बिना सबस्क्रिप्शन लिए शर्तों को समूहित करने का कोई तरीका है?


मुझे लगता है कि मैं बराबर अभिव्यक्ति का निर्धारण करने के लिए बूलियन तर्क का भी उपयोग कर सकता था: if ! [ -f file1 ] || ! [ -f file 2 ] || ! [ -f file3 ] ; thenलेकिन मैं अधिक सामान्य उत्तर चाहता हूं।
वाइल्डकार्ड

आप ब्रेसिज़ के अंदर भी नकार सकते हैं, जैसेif [[ ! -f file1 ]] && [[ ! -f file2 ]]; then
डोपघोटी

1
हां, मैंने अभी परीक्षण किया है if [ ! 1 -eq 2 ] && [ ! 2 -eq 3 ]; then echo yep; fiऔर यह काम करता है। मैं हमेशा आदत के रूप में डबल-ब्रेसेस के साथ परीक्षण लिखता हूं। इसके अलावा, यह सुनिश्चित करने के लिए कि bashमैंने आगे परीक्षण नहीं किया है if /bin/test ! 1 -eq 2 && /bin/test ! 2 -eq 3 ; then echo yep; fiऔर यह इस तरह से भी काम करता है।
डोपघोटी

1
@Wildcard - [ ! -e file/. ] && [ -r file ]निर्देशिका छोड़ देंगे। आप इसे पसंद करते हैं। बेशक, यही -dकरता है।
mikeserv

1
संबंधित प्रश्न (समान लेकिन उतनी चर्चा और उत्तर इतने उपयोगी नहीं): unix.stackexchange.com/q/156885/135943
Wildcard

जवाबों:


32

आपको { list;}इसके बजाय उपयोग करने की आवश्यकता है (list):

if ! { [ -f file1 ] && [ -f file2 ] && [ -f file3 ]; }; then
  : do something
fi

ये दोनों ग्रुपिंग कमांड हैं , लेकिन { list;}वर्तमान शेल वातावरण में कमांड निष्पादित करते हैं।

ध्यान दें कि, ;में { list;}से सूची पृथक करने के लिए की जरूरत है }रिवर्स शब्द, आप अच्छी तरह से अन्य सीमांकक उपयोग कर सकते हैं। अंतरिक्ष (या अन्य सीमांकक) के बाद {भी आवश्यक है।


धन्यवाद! कुछ ऐसा है जो मुझे पहली बार में ऊपर फिसल गया (के बाद से मैं में घुंघराले ब्रेसिज़ का उपयोग awkकी तुलना में अधिक बार bash) खुला घुंघराले ब्रेस के बाद खाली स्थान के लिए की जरूरत है। आप "आप अन्य सीमांकक का भी उपयोग कर सकते हैं" का उल्लेख करते हैं; कोई उदाहरण?
वाइल्डकार्ड 18

@Wildcard: हां, खुले घुंघराले ब्रेस के बाद व्हॉट्सएप की जरूरत है। अन्य परिसीमन के लिए एक उदाहरण एक नई रूपरेखा है, जैसा कि आप अक्सर चाहते हैं कि आप एक फ़ंक्शन को परिभाषित कर रहे हैं।
cuonglm

@don_crissti: में zsh, आप
व्हाट्सएप का

@don_crissti: &यह भी एक विभाजक है, आप उपयोग कर सकते हैं { echo 1;:&}, कई न्यूलाइन का भी उपयोग कर सकते हैं।
congonglm

2
आप मैनुअल से किसी भी मेटाचैकर उद्धरण का उपयोग कर सकते हैं they must be separated from list by whitespace or another shell metacharacter.बाश में वे हैं metacharacter: | & ; ( ) < > space tab :। इस विशिष्ट कार्य के लिए, मेरा मानना ​​है कि कोई भी & ; ) space tabकाम करेगा। .... .... zsh से (एक टिप्पणी के रूप में) each sublist is terminated by :; ', &', & |',&!', or a newline.

8

आप testजो चाहते हैं उसे प्राप्त करने के लिए पूरी तरह से कार्यक्षमता का उपयोग कर सकते हैं। के मैन पेज से test:

 ! expression  True if expression is false.
 expression1 -a expression2
               True if both expression1 and expression2 are true.
 expression1 -o expression2
               True if either expression1 or expression2 are true.
 (expression)  True if expression is true.

तो आपकी हालत ऐसी दिख सकती है:

if [ -f file1 -a -f file2 -a -f file3 ] ; then
    # do stuff with the files
fi

नकारात्मक उपयोग के लिए बच गए कोष्ठक:

if [ ! \( -f file1 -a -f file2 -a -f file3 \) ] ; then
    echo "Error: You done goofed."
    exit 1
fi
# do stuff with the files

6

करने के लिए portably खोल में एक जटिल सशर्त नकारना, आप या तो लागू करना चाहिए डी मॉर्गन के नियम और अंदर नीचे निषेध सभी तरह धक्का [कॉल ...

if [ ! -f file1 ] || [ ! -f file2 ] || [ ! -f file3 ]
then
    # do stuff
fi

... या आप का उपयोग करना चाहिए then :; else...

if [ -f file1 ] && [ -f file2 ] && [ -f file3 ]
then :
else
  # do stuff
fi

if ! commandकुछ भी उपलब्ध नहीं है और न ही है [[

यदि आपको कुल पोर्टेबिलिटी की आवश्यकता नहीं है, तो शेल स्क्रिप्ट न लिखें । आप वास्तव में आप की तुलना में बेतरतीब ढंग से चयनित यूनिक्स पर खोजने की अधिक संभावना रखते /usr/bin/perlहैं bash


1
!POSIX है जो आजकल पोर्टेबल-पर्याप्त है। यहां तक ​​कि सिस्टम जो अभी भी बॉर्न शेल के साथ जहाज करते हैं, उनके पास फाइल सिस्टम पर कहीं और एक पोसिक्स श है, जिसका उपयोग आप अपने सिंटैक्स सिंटैक्स की व्याख्या करने के लिए कर सकते हैं।
स्टीफन चेज़लस

@ स्टीफनचेज़लस यह तकनीकी रूप से सच है, लेकिन मेरे अनुभव में पर्ल में एक स्क्रिप्ट को फिर से लिखना आसान है क्योंकि इससे शुरू होने वाले पॉसिक्स-कंप्लायंट शेल वातावरण को सक्रिय करने और सक्रिय करने की परेशानी से निपटना है /bin/sh। जैसा कि आप सुझाव देते हैं, वैसे ही Autoconf स्क्रिप्ट करती है, लेकिन मुझे लगता है कि हम सभी जानते हैं कि यह कितना कम है।
zwol

5

अन्य लोगों ने {यौगिक कमांड ;}ग्रुपिंग को नोट किया है , लेकिन यदि आप एक सेट पर समान परीक्षण कर रहे हैं तो आप एक अलग तरह का उपयोग करना पसंद कर सकते हैं:

if  ! for f in file1 file2 file3
      do  [ -f "$f" ] || ! break
      done
then  : do stuff
fi

... जैसा कि कहीं और दिखाया गया है { :;}, घोंसले के शिकार कमांड के साथ कोई कठिनाई शामिल नहीं है ...

ध्यान दें कि नियमित फ़ाइलों के लिए ऊपर (आमतौर पर) परीक्षण । यदि आप केवल मौजूदा , पठनीय फ़ाइलों की तलाश कर रहे हैं जो निर्देशिका नहीं हैं:

if  ! for f in file1 file2 file3
      do  [ ! -d "$f" ] && 
          [   -r "$f" ] || ! break
      done
then  : do stuff
fi

अगर आपको परवाह नहीं है कि वे निर्देशिका हैं या नहीं:

if  ! command <file1 <file2 <file3
then  : do stuff
fi

... किसी भी पठनीय , सुलभ फ़ाइल के लिए काम करता है , लेकिन संभवतः पंद्रह डब्ल्यू / आउट लेखकों के लिए लटका होगा।


2

यह आपके मुख्य प्रश्न का पूर्ण-उत्तर नहीं है, लेकिन मैंने देखा कि आप एक टिप्पणी में यौगिक परीक्षण (पठनीय फ़ाइल) का उल्लेख करते हैं; जैसे,

if [ -f file1 ] && [ -r file1 ] && [ -f file2 ] && [ -r file2 ] && [ -f file3 ] && [ -r file3 ]

शेल फ़ंक्शन को परिभाषित करके आप इसे थोड़ा मजबूत कर सकते हैं; जैसे,

readable_file()
{
    [ -f "$1" ]  &&  [ -r "$1" ]
}

[ $# = 1 ]स्वाद में त्रुटि हैंडलिंग (जैसे ) जोड़ें। ifऊपर दिया गया पहला कथन, अब इसे संक्षिप्त किया जा सकता है

if readable_file file1  &&  readable_file file2  &&  readable_file file3

और आप फ़ंक्शन के नाम को छोटा करके इसे और भी छोटा कर सकते हैं। इसी तरह, आप परिभाषित कर सकते हैं not_readable_file()(या nrfसंक्षेप में) और फ़ंक्शन में नकार को शामिल कर सकते हैं।


अच्छा लगा, लेकिन सिर्फ एक लूप क्यों नहीं जोड़ा गया? readable_files() { [ $# -eq 0 ] && return 1 ; for file in "$@" ; do [ -f "$file" ] && [ -r "$file" ] || return 1 ; done ; } (अस्वीकरण: मैंने इस कोड का परीक्षण किया और यह काम करता है, लेकिन यह एक-लाइनर नहीं था। मैंने यहां पोस्ट करने के लिए अर्धविराम जोड़े, लेकिन उनके प्लेसमेंट का परीक्षण नहीं किया।)
Wildcard

1
अच्छी बात। मैं छोटी चिंता को बढ़ाऊंगा कि यह फ़ंक्शन में नियंत्रण (संयोजन) के तर्क को अधिक छिपाता है; कोई ऐसा जो स्क्रिप्ट पढ़ता है और देखता है if readable_files file1 file2 file3नहीं होगा पता है कि क्या समारोह कर रहा था और या या - हालांकि (क) मुझे लगता है कि यह काफी सहज है, (ख) यदि आप स्क्रिप्ट वितरण नहीं कर रहे हैं, यह अच्छा पर्याप्त है, तो आप यह समझते हैं, और (ग) चूंकि मैंने समारोह के नाम को अस्पष्टता में संक्षिप्त करने का सुझाव दिया था, इसलिए मैं पठनीयता के बारे में बात करने की स्थिति में नहीं हूं। … (Cont'd)
G-Man कहते हैं मोनिका '

1
(जारी) ... BTW, समारोह ठीक तरह से आप यह लिखा है, लेकिन आप बदल सकते हैं for file in "$@" ; doके साथ for file do- यह करने के लिए डिफ़ॉल्ट in "$@"(कुछ जवाबी intuitively), और ;केवल अनावश्यक नहीं, लेकिन वास्तव में हतोत्साहित किया है।
जी-मैन का कहना है कि 'मोनिका'

0

आप ब्रेस परीक्षणों के अंदर भी नकार सकते हैं, इसलिए अपने मूल कोड का पुन: उपयोग करें:

if [[ ! -f file1 ]] || [[ ! -f file2 ]] || [[ ! -f file3 ]] ; then
  # do stuff with the files
fi

2
आपको इसकी आवश्यकता ||है&&
cuonglm

परीक्षण " कोई भी फाइल नहीं है" नहीं है, परीक्षण " कोई भी फाइल नहीं है" है। का उपयोग करते हुए ||विधेय पर अमल होता अगर किसी भी फाइल के मौजूद नहीं हैं, नहीं तो और केवल iff सभी फ़ाइलों के मौजूद नहीं हैं। नहीं (ए और बी और सी) के रूप में ही है (ए नहीं) और (नहीं बी) और (नहीं सी); मूल प्रश्न देखें।
डोपघोटी

@ डोपघोटी, क्यूंग्लम सही है। यदि ऐसा नहीं है (तो वहां सभी फाइलें) तो जब आप इसे इस तरह से विभाजित करते हैं तो आपको इसकी आवश्यकता होती ||है &&। मेरे सवाल के नीचे मेरी पहली टिप्पणी देखें।
वाइल्डकार्ड 18

2
@ डोपघोटी: के not (a and b)रूप में ही है (not a) or (not b)En.wikipedia.org/wiki/De_Morgan%27s_laws
cuonglm

1
यह गुरुवार होना चाहिए। मैं कभी भी गुरुवार की फांसी नहीं पा सकता था। सही किया गया, और मैं अपने पैर-में-मुँह पोस्टेरिटी के लिए छोड़ दूंगा।
डोपगोटी 18

-1

मैं उन्हें केवल समूह बनाने के लिए उपयोग करना चाहता हूं, लेकिन क्या यह वास्तव में एक उपधारा पैदा कर रहा है? (मेरे लिए कहना मुश्कित है?)

हां, एक कमांड (...)एक उपधारा में चलाए जा रहे हैं।

यह जांचने के लिए कि क्या आप किसी सबस्लेम में हैं, आप अपने मौजूदा शेल के पीआईडी ​​की तुलना इंटरेक्टिव शेल के पीआईडी ​​से कर सकते हैं।

echo $BASHPID; (echo $BASHPID); 

उदाहरण आउटपुट, यह दर्शाता है कि कोष्ठक एक उपधारा और घुंघराले ब्रेसों को नहीं बनाते हैं:

$ echo $BASHPID; (echo $BASHPID); { echo $BASHPID;}
50827
50843
50827
$ 

6
()क्या आपके पास का अर्थ {}
है..अपने

@ हेमायल, यह मेरे प्रश्न का दूसरा भाग है- क्या कोई तरीका है जो मैं अपनी स्क्रीन पर देख सकता हूं या प्रदर्शित कर सकता हूं कि क्या उपसमूह का तथ्य सामने आया है? (यह वास्तव में एक अलग प्रश्न हो सकता है, लेकिन यहां जानना अच्छा होगा।)
वाइल्डकार्ड

1
@heemayl तुम सही हो! मैंने echo $$ && ( echo $$ )पीआईडी ​​की तुलना करने के लिए किया था और वे एक ही थे लेकिन इससे पहले कि मैं टिप्पणी प्रस्तुत करता आपको बता रहा था कि आप गलत थे मैंने एक और बात की कोशिश की। echo $BASHPID && ( echo $BASHPID )अलग-अलग पीआईडी ​​देता है
डेविड किंग

1
@heemayl echo $BASHPID && { echo $BASHPID; }आपको जैसा सुझाव देगा वैसा ही PID दें। शिक्षा के लिए धन्यवाद
डेविड किंग

@DavidKing, परीक्षण कमांड का उपयोग करने के लिए धन्यवाद $BASHPID, वह दूसरी चीज़ जो मुझे याद आ रही थी।
वाइल्डकार्ड 18
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.