আমি কীভাবে কোনও প্রক্রিয়াটির রিটার্ন-মান উপেক্ষা করতে পারি?


101

আমি একটি সহজ, কিন্তু ক্রস-প্ল্যাটফর্ম খুঁজছি অস্বীকার -process যে মান একটি প্রক্রিয়া আয় negates। এটি 0 থেকে কিছু মান মানচিত্র করা উচিত! = 0 এবং যে কোনও মান! = 0 থেকে 0, অর্থাত নীচের কমান্ডটি "হ্যাঁ, অস্তিত্বহীন কোনও অবস্থান নেই" ফিরে আসতে হবে:

 ls nonexistingpath | negate && echo "yes, nonexistingpath doesn't exist."

দ্য ! - অপারেটর দুর্দান্ত তবে দুর্ভাগ্যক্রমে শেল-স্বতন্ত্র নয়।


কৌতূহলের বাইরে, আপনার কি মনে একটি নির্দিষ্ট সিস্টেম রয়েছে যা ডিফল্টরূপে বাশকে অন্তর্ভুক্ত করে না? আমি "ক্রস-প্ল্যাটফর্ম" দ্বারা ধরে নিয়েছি আপনি ঠিক * নিক্স-ভিত্তিক বোঝাতে চেয়েছেন, যেহেতু আপনি একটি উত্তর গ্রহণ করেছেন যা কেবলমাত্র * নিক্স সিস্টেমে কাজ করবে।
পার্থিয়ান শট

উত্তর:


110

পূর্বে, উত্তরটি এখন প্রথম বিভাগ হিসাবে শেষ বিভাগ হিসাবে উপস্থিত ছিল।

পসিক্স শেলটিতে একটি !অপারেটর অন্তর্ভুক্ত

অন্যান্য সমস্যার জন্য শেল স্পেসিফিকেশনটির আশেপাশে কব্জি করা, আমি সম্প্রতি (সেপ্টেম্বর 2015) লক্ষ্য করেছি যে পসিক্স শেল একটি !অপারেটরকে সমর্থন করে । উদাহরণস্বরূপ, এটি একটি সংরক্ষিত শব্দ হিসাবে তালিকাভুক্ত এবং পাইপলাইনের শুরুতে উপস্থিত হতে পারে - যেখানে একটি সাধারণ কমান্ডটি 'পাইপলাইন' এর একটি বিশেষ কেস। এটি, সুতরাং, ifবিবৃতিতে এবং whileবা untilলুপগুলিতেও ব্যবহার করা যেতে পারে - পসিক্স-অনুবর্তী শেলগুলিতে। ফলস্বরূপ, আমার রিজার্ভেশন সত্ত্বেও, এটি সম্ভবত ২০০৮ সালে আমি যা বুঝতে পেরেছিলাম তার চেয়ে বেশি বিস্তৃতভাবে উপলভ্য। POSIX 2004 এবং SUS / POSIX 1997 এর একটি দ্রুত চেক দেখায় যা !উভয় সংস্করণে উপস্থিত ছিল।

নোট করুন !অপারেটরটি অবশ্যই পাইপলাইনের শুরুতে উপস্থিত হবে এবং পুরো পাইপলাইনের স্থিতি কোডটি (যেমন শেষ আদেশটি) উপেক্ষা করবে । এখানে কিছু উদাহরণঃ.

# Simple commands, pipes, and redirects work fine.
$ ! some-command succeed; echo $?
1
$ ! some-command fail | some-other-command fail; echo $?
0
$ ! some-command < succeed.txt; echo $?
1

# Environment variables also work, but must come after the !.
$ ! RESULT=fail some-command; echo $?
0

# A more complex example.
$ if ! some-command < input.txt | grep Success > /dev/null; then echo 'Failure!'; recover-command; mv input.txt input-failed.txt; fi
Failure!
$ ls *.txt
input-failed.txt

বহনযোগ্য উত্তর - অ্যান্টিক শেলগুলির সাথে কাজ করে

বোর্নে (কর্ন, পসিক্স, ব্যাশ) স্ক্রিপ্টে আমি ব্যবহার করি:

if ...command and arguments...
then : it succeeded
else : it failed
fi

এটি যত তাড়াতাড়ি পোর্টেবল হয়। 'কমান্ড এবং আর্গুমেন্ট' কমান্ডের পাইপলাইন বা অন্যান্য যৌগিক ক্রম হতে পারে।

একটি notআদেশ

দ্য '!' অপারেটর, আপনার শেলটিতে অন্তর্নির্মিত হোক বা o / s দ্বারা সরবরাহিত, সর্বজনীনভাবে উপলভ্য নয়। যদিও এটি লেখার জন্য ভয়ঙ্করভাবে কঠিন নয় - নীচের কোডটি কমপক্ষে ১৯৯১ সাল পর্যন্ত রয়েছে (যদিও আমি মনে করি আমি এর আগের সংস্করণটি আরও অনেক আগে লিখেছি)। যদিও আমি এটি আমার স্ক্রিপ্টগুলিতে ব্যবহার করি না, কারণ এটি নির্ভরযোগ্যভাবে উপলভ্য নয়।

/*
@(#)File:           $RCSfile: not.c,v $
@(#)Version:        $Revision: 4.2 $
@(#)Last changed:   $Date: 2005/06/22 19:44:07 $
@(#)Purpose:        Invert success/failure status of command
@(#)Author:         J Leffler
@(#)Copyright:      (C) JLSS 1991,1997,2005
*/

#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "stderr.h"

#ifndef lint
static const char sccs[] = "@(#)$Id: not.c,v 4.2 2005/06/22 19:44:07 jleffler Exp $";
#endif

int main(int argc, char **argv)
{
    int             pid;
    int             corpse;
    int             status;

    err_setarg0(argv[0]);

    if (argc <= 1)
    {
            /* Nothing to execute. Nothing executed successfully. */
            /* Inverted exit condition is non-zero */
            exit(1);
    }

    if ((pid = fork()) < 0)
            err_syserr("failed to fork\n");

    if (pid == 0)
    {
            /* Child: execute command using PATH etc. */
            execvp(argv[1], &argv[1]);
            err_syserr("failed to execute command %s\n", argv[1]);
            /* NOTREACHED */
    }

    /* Parent */
    while ((corpse = wait(&status)) > 0)
    {
            if (corpse == pid)
            {
                    /* Status contains exit status of child. */
                    /* If exit status of child is zero, it succeeded, and we should
                       exit with a non-zero status */
                    /* If exit status of child is non-zero, if failed and we should
                       exit with zero status */
                    exit(status == 0);
                    /* NOTREACHED */
            }
    }

    /* Failed to receive notification of child's death -- assume it failed */
    return (0);
}

কমান্ডটি কার্যকর করতে ব্যর্থ হলে এটি ব্যর্থতার বিপরীতে 'সাফল্য' দেয়। 'সাফল্যের সাথে কিছুই করবেন না' বিকল্পটি সঠিক ছিল কিনা তা নিয়ে আমরা বিতর্ক করতে পারি; যখন এটি কিছু করার জন্য বলা না হয় তখন এটি একটি ত্রুটির প্রতিবেদন করা উচিত। ' "stderr.h"' এ কোডটি সাধারণ ত্রুটির প্রতিবেদন করার সুবিধা সরবরাহ করে - আমি এটি সর্বত্র ব্যবহার করি। অনুরোধে উত্স কোড - আমার সাথে যোগাযোগ করতে আমার প্রোফাইল পৃষ্ঠা দেখুন।


'কমান্ড এবং আর্গুমেন্ট' এর জন্য +1 পাইপলাইন বা কমান্ডের অন্যান্য যৌগিক অনুক্রম হতে পারে। অন্যান্য সমাধান পাইপলাইন দিয়ে কাজ করে না
HVNSweeting

4
ব্যাশ পরিবেশের ভেরিয়েবলগুলি অবশ্যই !অপারেটরকে অনুসরণ করবে follow এটি আমার পক্ষে কাজ করেছে:! MY_ENV=value my_command
ড্যানিয়েল বোহমার

4
প্রত্যাখ্যান পুরো পাইপে কাজ করে, তাই আপনি করতে ldd foo.exe | ! grep badlibপারবেন না ! ldd foo.exe | grep badlibতবে আপনি যদি foo.exe এ বাদলিব না পাওয়া যায় তবে প্রস্থান স্থিতি 0 হতে চান আপনি করতে পারেন । শব্দার্থকভাবে আপনি grepস্থিতিটি উল্টাতে চান , তবে পুরো পাইপটি উল্টানো একই ফলাফল দেয়।
লাকাটা

@ মার্কলাকাটা: আপনি ঠিক বলেছেন: পসিক্স শেল সিনট্যাক্সটি দেখুন ও সংশ্লিষ্ট বিভাগে (যেতে POSIX সেরা look'n'feel জন্য)। তবে এটি ব্যবহার করা সম্ভব ldd foo.exe | { ! grep badlib; }(যদিও এটি উপদ্রব, বিশেষত অর্ধকোলন; আপনি সেমিকোলনের সাথে (এবং তার বাইরেও একটি সম্পূর্ণ সাব-শেল ব্যবহার করতে পারেন ))। OTOH, অবজেক্টটি হ'ল পাইপলাইনের প্রস্থান স্থিতিটি উল্টানো এবং এটি হ'ল শেষ কমান্ডের প্রস্থান স্থিতি (কখনও কখনও বাশ ব্যতীত)।
জোনাথন লেফলার

4
এই উত্তর অনুযায়ী! কমান্ড সহ একটি অবাঞ্ছিত মিথস্ক্রিয়া আছে set -eঅর্থাৎ কম্যান্ড পরিবর্তে শুধুমাত্র একটি নন-জিরো প্রস্থান কোড সহ সাফল্যলাভের, একটি 0 বা নন-জিরো প্রস্থান কোড সহ সফল করতে ঘটায়। কেবলমাত্র একটি শূন্য-বহির্গমন কোড দিয়ে এটিকে সফল করার কোনও সংক্ষিপ্ত উপায় আছে ?
এলিয়ট স্লটার

40

বাশে, ব্যবহার করুন! কমান্ডের আগে অপারেটর এই ক্ষেত্রে:

! ls nonexistingpath && echo "yes, nonexistingpath doesn't exist"

17

আপনি চেষ্টা করতে পারেন:

ls nonexistingpath || echo "yes, nonexistingpath doesn't exist."

অথবা শুধুই:

! ls nonexistingpath

4
দুর্ভাগ্যক্রমে !ব্যবহার করা যাবে না git bisect run, বা কমপক্ষে আমি জানি না।
আটটিলা ও

4
আপনি সর্বদা শেল স্ক্রিপ্টে স্টাফ রাখতে পারেন; গিট বাইসেক্ট রান !সেই ক্ষেত্রে দেখতে পাচ্ছে না ।
টুলফোজার 20

10

যদি কোনওভাবে ঘটে থাকে যে আপনার শেল হিসাবে আপনার কাছে বাশ নেই (যেমন: গিট স্ক্রিপ্টস, বা পুতুল এক্সিকিউট পরীক্ষা) আপনি চালাতে পারেন:

echo '! ls notexisting' | bash

-> retcode: 0

echo '! ls /' | bash

-> retcode: 1


4
এখানে আরেকটি ব্রেডক্রাম্ব রাখতে, ট্র্যাভিস-সিআই-র স্ক্রিপ্ট বিভাগে লাইনগুলির জন্য এটি প্রয়োজনীয়।
কেজিরেণে

এটি বিটবাকেট পাইপলাইনের জন্যও প্রয়োজনীয় ছিল।
কুমজ

3
! ls nonexistingpath && echo "yes, nonexistingpath doesn't exist."

বা

ls nonexistingpath || echo "yes, nonexistingpath doesn't exist."

আমি অনুলিপি করেছিলাম যদি আসল প্রশ্ন থেকে, আমি ভেবেছিলাম এটি একটি পাইপলাইনের অংশ, আমি মাঝে মাঝে কিছুটা ধীর হয়ে থাকি;)
রবার্ট গ্যাম্বল

এই দুটি বিবৃতি প্রায় সমতুল্য, তবে ফিরে থাকা মানটি $?ভিন্ন হবে। প্রকৃত উপস্থিতি $?=1থাকলে প্রথমটি ছেড়ে যেতে nonexistingpathপারে। দ্বিতীয়টি সর্বদা চলে যায় $?=0। আপনি যদি এটি কোনও মেকফাইলে ব্যবহার করে থাকেন এবং ফেরতের মূল্যের উপর নির্ভর করতে হয় তবে আপনাকে সতর্কতা অবলম্বন করতে হবে।
লাকাটা

1

দ্রষ্টব্য: কখনও কখনও আপনি দেখতে পাবেন !(command || other command)
এখানে ! ls nonexistingpath && echo "yes, nonexistingpath doesn't exist."যথেষ্ট।
সাব-শেলের দরকার নেই।

গিট 2.22 (কিউ 2 2019) এর সাথে আরও ভাল ফর্মটি চিত্রিত করে:

74ec8cf কমিট , 3fae7ad কমিট , 0e67c32 কমিট , 07353d9 কমিট , 3bc2702 কমিট , 8c3b9f7 কমিট , 80a539a কমিট , c5c39f4 কমিট (13 মার্চ 2019) দ্বারা SZEDER গাবর ( szeder)
দেখুন কমিট 99e37c2 , 9f82b2a কমিট , কমিট 900721e (13 মার্চ 2019) দ্বারা জোহানেস Schindelin ( dscho)
(দ্বারা একীভূত junio সি Hamano - gitster- মধ্যে কমিট 579b75a , 25 এপ্রিল 2019)

t9811-git-p4-label-import: পাইপলাইন অবহেলা ঠিক করুন

' t9811-git-p4-label-import.sh' তে, পরীক্ষা ' tag that cannot be exported' চালায়:

!(p4 labels | grep GIT_TAG_ON_A_BRANCH)

প্রদত্ত স্ট্রিংটি ' p4 labels' দ্বারা মুদ্রিত হয়নি তা পরীক্ষা করতে to
এটি সমস্যাযুক্ত কারণ পসিক্সের মতে :

"যদি পাইপলাইনটি সংরক্ষিত শব্দের সাথে শুরু হয় !এবং command1সাবসেল কমান্ড হয় তবে অ্যাপ্লিকেশনটি নিশ্চিত করবে যে (প্রারম্ভিকালে অপারেটরটিকে এক বা একাধিক অক্ষর দ্বারা command1পৃথক করা হয় immediately অপারেটরের সাথে সাথে অনুসরণ করা সংরক্ষিত শব্দের আচরণ অনির্দিষ্ট। "!<blank>
!(

যদিও বেশিরভাগ সাধারণ শেলগুলি এখনও এই ' !'টিকে "পাইপলাইনে শেষ কমান্ডের প্রস্থান কোড অবহেলা" mksh/lkshহিসাবে ব্যাখ্যা করে ,' 'এর পরিবর্তে এটি নেতিবাচক ফাইলের নাম ধরণ হিসাবে ব্যাখ্যা করবেন না।
ফলস্বরূপ, তারা বর্তমান ডিরেক্টরিতে প্যাথনামগুলি দিয়ে তৈরি একটি কমান্ড চালানোর চেষ্টা করে (এতে ' main' নামে একটি একক ডিরেক্টরি রয়েছে ) যা অবশ্যই পরীক্ষায় ব্যর্থ হয়।

আমরা ' !' এবং ' (' এর মধ্যে একটি স্পেস যোগ করে এটি ঠিক করতে পারতাম , তবে এর পরিবর্তে অপ্রয়োজনীয় সাবશેলটি সরিয়ে এটি ঠিক করতে পারি। বিশেষত, কমিট 74ec8cf c


1

সমাধান ছাড়াই!, সাবহেল ছাড়াই, যদি না হয় এবং কমপক্ষে ব্যাশে কাজ করা উচিত:

ls nonexistingpath; test $? -eq 2 && echo "yes, nonexistingpath doesn't exist."

# alternatively without error message and handling of any error code > 0
ls nonexistingpath 2>/dev/null; test $? -gt 0 && echo "yes, nonexistingpath doesn't exist."
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.