पर्ल में, यदि $ चर को परिभाषित किया जाता है और एक शून्य शून्य लंबाई स्ट्रिंग होती है, तो मैं कैसे संक्षेप में जांच कर सकता हूं?


83

मैं वर्तमान में निम्न चर का उपयोग यह जांचने के लिए करता हूं कि क्या कोई चर परिभाषित किया गया है और पाठ शामिल है। defined'अनइंस्टाल्ड वैल्यू' की चेतावनी से बचने के लिए मुझे पहले जाँच करनी होगी :

if (defined $name && length $name > 0) {
    # do something with $name
}

क्या इसे लिखने का एक बेहतर (संभवतः अधिक संक्षिप्त) तरीका है?

जवाबों:


80

आप अक्सर परिभाषितता के लिए चेक देखते हैं ताकि आपको एक अपरिभाषित मान का उपयोग करने के लिए चेतावनी से निपटना न पड़े (और पर्ल 5.10 में यह आपको आक्रामक चर बताता है):

 Use of uninitialized value $name in ...

इसलिए, इस चेतावनी को प्राप्त करने के लिए, लोग सभी प्रकार के कोड के साथ आते हैं, और यह कोड बबल गम और डक्ट टेप के बजाय समाधान के एक महत्वपूर्ण हिस्से की तरह दिखाई देने लगता है। कभी-कभी, यह दिखाने के लिए बेहतर है कि आप उस चेतावनी को स्पष्ट रूप से बंद कर रहे हैं जिसे आप बचने की कोशिश कर रहे हैं:

 {
 no warnings 'uninitialized';

 if( length $name ) {
      ...
      }
 }

अन्य मामलों में, डेटा के बजाय किसी प्रकार के शून्य मान का उपयोग करें। साथ Perl 5.10 परिभाषित या ऑपरेटर , आप दे सकते हैं lengthचर कि चेतावनी ट्रिगर किया जाएगा के बजाय एक स्पष्ट रिक्त स्ट्रिंग (परिभाषित है, और वापस शून्य लम्बाई देना):

 use 5.010;

 if( length( $name // '' ) ) {
      ...
      }

पर्ल 5.12 में, यह थोड़ा आसान है क्योंकि lengthअपरिभाषित मूल्य पर भी अपरिभाषित रिटर्न होता है । यह थोड़ा खिन्नता जैसा लग सकता है, लेकिन यह उस गणितज्ञ को प्रसन्न करता है जो मैं चाहता था। यह चेतावनी जारी नहीं करता है, यही कारण है कि यह सवाल मौजूद है।

use 5.012;
use warnings;

my $name;

if( length $name ) { # no warning
    ...
    }

4
इसके अलावा, v5.12 और बाद में, length undefचेतावनी के बजाय अनिर्धारित रिटर्न देता है, और 0. रिटर्न बूलियन संदर्भ में, अपराजित केवल 0 के रूप में गलत है, इसलिए यदि आप v5.12 या बाद में लक्षित कर रहे हैं, तो आप बस लिख सकते हैंif (length $name) { ... }
rjbs

24

जैसा कि मोबिलर बताता है, आप एक छोटी बचत के लिए निम्नलिखित का उपयोग कर सकते हैं:

if (defined $name && $name ne '') {
    # do something with $name
}

आप परिभाषित चेक को खोद सकते हैं और कुछ छोटा भी कर सकते हैं, जैसे:

if ($name ne '') {
    # do something with $name
}

लेकिन उस मामले में जहां $nameपरिभाषित नहीं किया गया है, हालांकि तर्क प्रवाह सिर्फ उद्देश्य के रूप में काम करेगा, यदि आप उपयोग कर रहे हैं warnings(और आपको होना चाहिए), तो आपको निम्नलिखित चेतावनी मिलेगी:

स्ट्रिंग ने में अनैतिक मूल्य का उपयोग

इसलिए, अगर ऐसा कोई अवसर है जिसे $nameपरिभाषित नहीं किया जा सकता है, तो आपको वास्तव में उस चेतावनी से बचने के लिए पहले और सबसे पहले परिभाषितता की जांच करने की आवश्यकता है। जैसा कि सिनान pointsnür बताते हैं, आप स्केलर :: MoreUtils का उपयोग कोड प्राप्त करने के लिए कर सकते हैं जो बिल्कुल ऐसा करता है (परिभाषितता के लिए जाँच करता है, फिर शून्य लंबाई की जाँच करता है) empty()विधि से, बॉक्स के बाहर :

use Scalar::MoreUtils qw(empty);
if(not empty($name)) {
    # do something with $name 
}

17

पहला, चूंकि lengthहमेशा एक गैर-नकारात्मक संख्या देता है,

if ( length $name )

तथा

if ( length $name > 0 )

समतुल्य हैं।

यदि आप खाली स्ट्रिंग के साथ अपरिभाषित मान को बदलने के लिए ठीक हैं, तो आप पर्ल 5.10 के //=ऑपरेटर का उपयोग कर सकते हैं जो LHS परिभाषित होने तक RHS को LHS प्रदान करता है:

#!/usr/bin/perl

use feature qw( say );
use strict; use warnings;

my $name;

say 'nonempty' if length($name //= '');
say "'$name'";

एक अपरिष्कृत चर के बारे में चेतावनियों की अनुपस्थिति को नोट करें क्योंकि $nameयह अपरिभाषित होने पर खाली स्ट्रिंग को सौंपा गया है।

हालाँकि, यदि आप स्थापित किए जा रहे 5.10 पर निर्भर नहीं होना चाहते हैं, तो स्केलर :: MoreUtils द्वारा प्रदान किए गए कार्यों का उपयोग करें । उदाहरण के लिए, ऊपर लिखा जा सकता है:

#!/usr/bin/perl

use strict; use warnings;

use Scalar::MoreUtils qw( define );

my $name;

print "nonempty\n" if length($name = define $name);
print "'$name'\n";

यदि आप क्लोबर नहीं करना चाहते हैं $name, तो उपयोग करें default


+1 के लिए "// =" उल्लेख (मुझे कैसे पता चलेगा कि सिनान का जवाब होगा :)
DVK

4
मैं इस मामले में // = का उपयोग नहीं करूंगा क्योंकि यह डेटा को साइड इफेक्ट के रूप में बदलता है। इसके बजाय, थोड़ा कम का उपयोग करें length( $name // '' )
ब्रायन डी फ़ो सिप

@brian d'foy मुझे लगता है कि यह इस बात पर निर्भर करता है कि फ़ंक्शन में क्या किया जा रहा है।
सिनान Sepnür

+1 //और //=ऑपरेटर संभवतः अस्तित्व में सबसे उपयोगी विशेष ऑपरेटर हैं।
क्रिस लुत्ज

1
जैसा कि @rjbs ने मेरे उत्तर में बताया, v5.12 के साथ और बाद में lengthअब कुछ वापस कर सकते हैं जो एक संख्या नहीं है (लेकिन NaN नहीं;)
brian d foy

5

उन मामलों में जहां मुझे परवाह नहीं है कि चर undefया इसके बराबर है '', मैं आमतौर पर इसे संक्षेप में प्रस्तुत करता हूं:

$name = "" unless defined $name;
if($name ne '') {
  # do something with $name
}

पर्ल 5.10 में, इसे छोटा किया जा सकता है, $name //= "";जो कि सीन ने पोस्ट किया है।
क्रिस लुत्ज

और अगर आप 5.10 पर्ल की जरूरत नहीं है, आप अभी भी लिख सकते हैं$name ||= "";
आरईटी

1
@ रीट: आप उपयोग नहीं कर सकते हैं || यहाँ संचालक चूंकि स्ट्रिंग '0' को '' के साथ बदलता है। आपको यह जांचना होगा कि क्या यह परिभाषित है, सच नहीं है।
brian d foy

क्रिस, आरईटी: हाँ, मुझे पता है। मैं विशेष रूप से यह सुझाव देने की कोशिश कर रहा था कि अगर जेसिका के बीच अंतर नहीं था undefऔर "", उसे सिर्फ एक को दूसरे में बदलना चाहिए और एक परीक्षण का उपयोग करना चाहिए। यह सामान्य स्थिति में काम नहीं करेगा, जिसके लिए पोस्ट किए गए अन्य समाधान बेहतर तरीके से हैं, लेकिन इस विशिष्ट मामले में बड़े करीने से कोड होते हैं। क्या मुझे यह स्पष्ट करने के लिए अपने जवाब को वापस लेना चाहिए?
गौरव

1

तुम कह सकते हो

 $name ne ""

के बजाय

 length $name > 0

7
यह आपको अभी भी चेतावनी देगा। लोग सबसे पहले परिभाषित करते हैं कि 'अनइंस्टाल्ड वैल्यू' की चेतावनी से बचने के लिए जाँच की जाती है।
ब्रायन डी फॉय

1

सरल और सुरुचिपूर्ण तरीके से दोहराव वाली चीजें करना हमेशा संभव नहीं होता है।

जब आपके पास आम कोड हो तो बस वही करें जो कई परियोजनाओं में दोहराया जाता है:

CPAN खोजें, किसी के पास आपके लिए पहले से ही कोड हो सकता है। इस मुद्दे के लिए मुझे स्केलर :: MoreUtils मिला ।

यदि आपको CPAN पर कुछ पसंद नहीं है, तो एक मॉड्यूल बनाएं और कोड को एक सबरूटीन में डालें:

package My::String::Util;
use strict;
use warnings;
our @ISA = qw( Exporter );
our @EXPORT = ();
our @EXPORT_OK = qw( is_nonempty);

use Carp  qw(croak);

sub is_nonempty ($) {
    croak "is_nonempty() requires an argument" 
        unless @_ == 1;

    no warnings 'uninitialized';

    return( defined $_[0] and length $_[0] != 0 );
}

1;

=head1 BOILERPLATE POD

blah blah blah

=head3 is_nonempty

Returns true if the argument is defined and has non-zero length.    

More boilerplate POD.

=cut

फिर अपने कोड में इसे कॉल करें:

use My::String::Util qw( is_nonempty );

if ( is_nonempty $name ) {
    # do something with $name
}

या यदि आप प्रोटोटाइप पर आपत्ति और अतिरिक्त कोष्ठक पर आपत्ति नहीं है, मॉड्यूल में प्रोटोटाइप को छोड़, और यह की तरह कहते हैं: is_nonempty($name)


2
क्या मक्खी को मारने के लिए हथौड़े का उपयोग करना पसंद नहीं है?
ज़ोरान सिमिक

4
@Zoran No. फैक्टरिंग कोड इस तरह से धड़कता है जैसे कई अलग-अलग स्थानों में एक जटिल स्थिति की प्रतिकृति होती है। यह एक हाथी को मारने के लिए पिनपिक्स का उपयोग करने जैसा होगा। @daotoad: मुझे लगता है कि आपको इसके उपयोग पर जोर देने के लिए अपना जवाब छोटा करना चाहिए Scalar::MoreUtils
सिनान Sepnür

@ जोरान: स्केलर :: MoreUtils बिना किसी निर्भरता के साथ एक बहुत ही हल्का मॉड्यूल है। इसके शब्दार्थ भी सर्वविदित हैं। जब तक आपको CPAN से एलर्जी नहीं होती है, तब तक इसका उपयोग करने से बचने का कोई कारण नहीं है।
एडम बेलायर

1
@ क्रिस लुत्ज़, हाँ, मुझे नहीं करना चाहिए। लेकिन प्रोटोटाइप अर्ध-टूटे हुए हैं - प्रोटोटाइप प्रवर्तन को तोड़ने के लिए आसान तरीके हैं। उदाहरण के लिए, भद्दे और / या पुराने ट्यूटोरियल &फ़ंक्शन को कॉल करते समय सजग के उपयोग को प्रोत्साहित करना जारी रखते हैं । इसलिए मैं सभी काम करने के लिए प्रोटोटाइप पर निर्भर नहीं हूं। मुझे लगता है कि मैं "जोड़ सकता हूं और उप कॉल पर & sigil का उपयोग करना छोड़ सकता हूं जब तक कि आप वास्तव में इसका मतलब नहीं है" त्रुटि संदेश के लिए।
दातरोड

1
यह प्रोटोटाइप के बारे में सोचना आसान है क्योंकि यह पर्ल कंपाइलर के संकेत के रूप में है, इसलिए यह जानता है कि किसी चीज़ को पार्स कैसे किया जाए। वे तर्क को मान्य करने के लिए वहाँ नहीं हैं। वे लोगों की उम्मीदों के संदर्भ में टूट सकते हैं, लेकिन बहुत सारी चीजें हैं। :)
brian d foy

1

उत्कृष्ट पुस्तकालय प्रकार :: टिनी एक रूपरेखा प्रदान करता है जिसके साथ अपने पर्ल कोड में टाइप-चेकिंग का निर्माण किया जाता है। मैं यहाँ जो दिखा रहा हूँ वह केवल हिमशैल का सबसे पतला सिरा है और सबसे सरल और मैनुअल तरीके से टाइप :: टिनी का उपयोग कर रहा है।

प्रकार की जाँच करना सुनिश्चित करें :: अधिक जानकारी के लिए टिनी :: मैनुअल

use Types::Common::String qw< NonEmptyStr >;

if ( NonEmptyStr->check($name) ) {
    # Do something here.
}

NonEmptyStr->($name);  # Throw an exception if validation fails

-2

कैसा रहेगा

if (length ($name || '')) {
  # do something with $name
}

यह आपके मूल संस्करण के बराबर नहीं है, क्योंकि यह $nameसंख्यात्मक मान 0 या स्ट्रिंग होने पर भी गलत वापस आ '0'जाएगा, लेकिन अन्य सभी मामलों में समान व्यवहार करेगा।

पर्ल 5.10 (या बाद में) में, उचित दृष्टिकोण इसके बजाय परिभाषित या ऑपरेटर का उपयोग करना होगा:

use feature ':5.10';
if (length ($name // '')) {
  # do something with $name
}

यह तय करेगा कि क्या $nameपरिभाषित किया गया है या नहीं, इसके आधार पर लंबाई प्राप्त करने के लिए , क्या यह सच है, इसलिए 0 / '0'उन मामलों को सही ढंग से संभाल लेंगे, लेकिन इसके लिए पर्ल के अधिक हाल के संस्करण की आवश्यकता होती है, जो कई लोगों के पास उपलब्ध है।


2
क्यों टूटे हुए घोल से केवल यह कहना कि यह टूट गया है?
ब्रायन डी फ़ो सिप

क्योंकि, जैसा कि मैंने भी उल्लेख किया है, 5.10 "कई लोगों की तुलना में पर्ल का एक और हालिया संस्करण उपलब्ध है।" YMMV, लेकिन "यह एक 99% समाधान है जिसे मैं जानता हूं कि आप इसका उपयोग कर सकते हैं, लेकिन एक बेहतर एक है जो शायद आप उपयोग कर सकते हैं, शायद आप" यहां मेरे लिए "बेहतर समाधान नहीं है, लेकिन आप शायद ऐसा कर सकते हैं ' t इसका उपयोग करें, इसलिए यहाँ एक विकल्प है जिसे आप कमबैक के रूप में प्राप्त कर सकते हैं। "
डेव शेरोहमान

1
पहले के पर्ल्स के साथ भी आपके पास एक टूटे हुए के बजाय एक काम कर समाधान हो सकता है।
ब्रायन डी फ़ो सिप

-3
अगर ($ नाम)
{
    #since अपराजित और '' दोनों ही असत्य का मूल्यांकन करते हैं 
    # यह तभी काम करना चाहिए जब स्ट्रिंग परिभाषित और गैर-रिक्त हो ...
    # जब तक आप $ नाम = "0" जैसे कुछ झूठ की उम्मीद कर रहे हैं, जो गलत है।
    # नोट हालांकि वह $ नाम = "00" गलत नहीं है
}

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