पाठ फ़ाइल में बेजोड़ कोष्ठक कैसे खोजें?


32

आज मुझे पता चला कि मैं perl -c filenameमनमाने ढंग से फाइलों में बेजोड़ घुंघराले कोष्ठक {} का उपयोग कर सकता हूं , जरूरी नहीं कि पर्ल स्क्रिप्ट्स। समस्या यह है, यह अन्य प्रकार के ब्रैकेट () [] और शायद <> के साथ काम नहीं करता है। मेरे पास कई Vim प्लगइन्स के साथ प्रयोग किए गए थे जो बेजोड़ कोष्ठक खोजने में मदद करने का दावा करते हैं लेकिन अभी तक इतना अच्छा नहीं है।

मेरे पास काफी कोष्ठक के साथ एक पाठ फ़ाइल है और उनमें से एक गायब है! क्या कोई प्रोग्राम / स्क्रिप्ट / विम प्लगइन / जो कुछ भी मुझे बेजोड़ कोष्ठक की पहचान करने में मदद कर सकता है?

जवाबों:


22

विम में आप उपयोग कर सकते हैं [और ]जल्दी से अगले कीस्ट्रोके में दर्ज किए गए प्रकार के निकटतम बेजोड़ ब्रैकेट की यात्रा कर सकते हैं ।

तो [{आपको नज़दीकी बेजोड़ "{" पर ले जाएगा; ])आपको आगे के बेजोड़ ")", और इसी तरह आगे ले जाएगा।


महान, यह मेरे लिए एकदम सही है। मैं इस उत्तर को स्वीकार करने वाला हूं, लेकिन केवल यह देखने के लिए इंतजार कर रहा है कि क्या कोई टेक्स्ट प्रोसेसिंग टूल है जो इसका विश्लेषण कर सकता है।
फुनेहे

6
मैं इसमें यह भी जोड़ूंगा कि आप जिस पर हैं, उसके मिलान ब्रैकेट को तुरंत ढूंढने के लिए आप% (शिफ्ट 5, यूएसए में) का उपयोग कर सकते हैं ।
atroon

@atroon ऊ, अच्छा। क्या वह अभी तक खुद को नहीं जानता था। मुझे कभी-कभी स्टैकएक्सचेंज पसंद है। :)
शादुर

क्या है <kbd> [</ kbd> और <kbd>] </ kbd> वास्तव में कूद रहा है
wirbel

मैंने लगभग एक दिन 4000 पंक्तियों से गुजरते हुए लापता को खोजने की कोशिश की} R में और यह उत्तर था। फिर, धन्यवाद VIM! लेकिन मुझे लगता है कि स्रोत कोड फ़ाइलों को छोटे खंडों में विभाजित करने के लिए यह एक अच्छा तर्क है।
थॉमस ब्राउने

7

अद्यतन 2:
निम्न स्क्रिप्ट अब एक बेमेल ब्रैकेट की पंक्ति संख्या और कॉलम प्रिंट करती है । यह एक ब्रैकेट प्रकार को स्कैन के आधार पर संसाधित करता है (यानी। ''] <>> '' {} '' () '...)
स्क्रिप्ट पहले , बेमिसाल दाएं ब्रैकेट या किसी भी अन-पेयर लेफ्ट ब्रैकेट की पहचान करता है। ... एरो का पता लगाने पर, यह लाइन और कॉलम नंबरों से बाहर निकल जाता है

यहाँ कुछ नमूना उत्पादन है ...


File = /tmp/fred/test/test.in
Pair = ()

*INFO:  Group 1 contains 1 matching pairs

ERROR: *END-OF-FILE* encountered after Bracket 7.
        A Left "(" is un-paired in Group 2.
        Group 2 has 1 un-paired Left "(".
        Group 2 begins at Bracket 3.
  see:  Line, Column (8, 10)
        ----+----1----+----2----+----3----+----4----+----5----+----6----+----7
000008  (   )    (         (         (     )   )                    

ये रही स्क्रिप्ट ...


#!/bin/bash

# Itentify the script
bname="$(basename "$0")"
# Make a work dir
wdir="/tmp/$USER/$bname"
[[ ! -d "$wdir" ]] && mkdir -p "$wdir"

# Arg1: The bracket pair 'string'
pair="$1"
# pair='[]' # test
# pair='<>' # test
# pair='{}' # test
# pair='()' # test

# Arg2: The input file to test
ifile="$2"
  # Build a test source file
  ifile="$wdir/$bname.in"
  cp /dev/null "$ifile"
  while IFS= read -r line ;do
    echo "$line" >> "$ifile"
  done <<EOF
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
[   ]    [         [         [
<   >    <         
                   <         >         
                             <    >    >         >
----+----1----+----2----+----3----+----4----+----5----+----6
{   }    {         }         }         }         } 
(   )    (         (         (     )   )                    
ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
EOF

echo "File = $ifile"
# Count how many: Left, Right, and Both
left=${pair:0:1}
rght=${pair:1:1}
echo "Pair = $left$rght"
# Make a stripped-down 'skeleton' of the source file - brackets only
skel="/tmp/$USER/$bname.skel" 
cp /dev/null "$skel"
# Make a String Of Brackets file ... (It is tricky manipulating bash strings with []..
sed 's/[^'${rght}${left}']//g' "$ifile" > "$skel"
< "$skel" tr  -d '\n'  > "$skel.str"
Left=($(<"$skel.str" tr -d "$left" |wc -m -l)); LeftCt=$((${Left[1]}-${Left[0]}))
Rght=($(<"$skel.str" tr -d "$rght" |wc -m -l)); RghtCt=$((${Rght[1]}-${Rght[0]}))
yBkts=($(sed -e "s/\(.\)/ \1 /g" "$skel.str"))
BothCt=$((LeftCt+RghtCt))
eleCtB=${#yBkts[@]}
echo

if (( eleCtB != BothCt )) ; then
  echo "ERROR:  array Item Count ($eleCtB)"
  echo "     should equal BothCt ($BothCt)"
  exit 1
else
  grpIx=0            # Keep track of Groups of nested pairs
  eleIxFir[$grpIx]=0 # Ix of First Bracket in a specific Group
  eleCtL=0           # Count of Left brackets in current Group 
  eleCtR=0           # Count of Right brackets in current Group
  errIx=-1           # Ix of an element in error.
  for (( eleIx=0; eleIx < eleCtB; eleIx++ )) ; do
    if [[ "${yBkts[eleIx]}" == "$left" ]] ; then
      # Left brackets are 'okay' until proven otherwise
      ((eleCtL++)) # increment Left bracket count
    else
      ((eleCtR++)) # increment Right bracket count
      # Right brackets are 'okay' until their count exceeds that of Left brackets
      if (( eleCtR > eleCtL )) ; then
        echo
        echo "ERROR:  MIS-matching Right \"$rght\" in Group $((grpIx+1)) (at Bracket $((eleIx+1)) overall)"
        errType=$rght    
        errIx=$eleIx    
        break
      elif (( eleCtL == eleCtR )) ; then
        echo "*INFO:  Group $((grpIx+1)) contains $eleCtL matching pairs"
        # Reset the element counts, and note the first element Ix for the next group
        eleCtL=0
        eleCtR=0
        ((grpIx++))
        eleIxFir[$grpIx]=$((eleIx+1))
      fi
    fi
  done
  #
  if (( eleCtL > eleCtR )) ; then
    # Left brackets are always potentially valid (until EOF)...
    # so, this 'error' is the last element in array
    echo
    echo "ERROR: *END-OF-FILE* encountered after Bracket $eleCtB."
    echo "        A Left \"$left\" is un-paired in Group $((grpIx+1))."
    errType=$left
    unpairedCt=$((eleCtL-eleCtR))
    errIx=$((${eleIxFir[grpIx]}+unpairedCt-1))
    echo "        Group $((grpIx+1)) has $unpairedCt un-paired Left \"$left\"."
    echo "        Group $((grpIx+1)) begins at Bracket $((eleIxFir[grpIx]+1))."
  fi

  # On error, get Line and Column numbers
  if (( errIx >= 0 )) ; then
    errLNum=0    # Source Line number (current).
    eleCtSoFar=0 # Count of bracket-elements in lines processed so far.
    errItemNum=$((errIx+1)) # error Ix + 1 (ie. "1 based")
    # Read the skeketon file to find the error line-number
    while IFS= read -r skline ; do
      ((errLNum++))
      brackets="${skline//[^"${rght}${left}"]/}" # remove whitespace
      ((eleCtSoFar+=${#brackets}))
      if (( eleCtSoFar >= errItemNum )) ; then
        # We now have the error line-number
        # ..now get the relevant Source Line 
        excerpt=$(< "$ifile" tail -n +$errLNum |head -n 1)
        # Homogenize the brackets (to be all "Left"), for easy counting
        mogX="${excerpt//$rght/$left}"; mogXCt=${#mogX} # How many 'Both' brackets on the error line? 
        if [[ "$errType" == "$left" ]] ; then
          # R-Trunc from the error element [inclusive]
          ((eleTruncCt=eleCtSoFar-errItemNum+1))
          for (( ele=0; ele<eleTruncCt; ele++ )) ; do
            mogX="${mogX%"$left"*}"   # R-Trunc (Lazy)
          done
          errCNum=$((${#mogX}+1))
        else
          # errType=$rght
          mogX="${mogX%"$left"*}"   # R-Trunc (Lazy)
          errCNum=$((${#mogX}+1))
        fi
        echo "  see:  Line, Column ($errLNum, $errCNum)"
        echo "        ----+----1----+----2----+----3----+----4----+----5----+----6----+----7"  
        printf "%06d  $excerpt\n\n" $errLNum
        break
      fi
    done < "$skel"
  else
    echo "*INFO:  OK. All brackets are paired."
  fi
fi
exit

यह स्क्रिप्ट शानदार है!
जोनाथन ड्यूमाइन

1
यह भयानक है, लेकिन यह हमेशा Line, Column (8, 10)कोई फर्क नहीं पड़ता है कि मैं किस फ़ाइल पर इसे आज़माता हूं। यह mogXCt=${#mogX}भी सेट है, लेकिन कहीं भी उपयोग नहीं किया गया है।
क्लेटन ड्यूक

5

सबसे अच्छा विकल्प शादुर द्वारा पहचाना गया vim / gvim है, लेकिन यदि आप एक स्क्रिप्ट चाहते हैं, तो आप स्टैक ओवरफ्लो पर एक समान प्रश्न के लिए मेरे उत्तर की जांच कर सकते हैं । मैं यहाँ अपना पूरा उत्तर दोहराता हूँ:

यदि आप जो करने की कोशिश कर रहे हैं वह एक सामान्य प्रयोजन की भाषा पर लागू होता है, तो यह एक गैर-तुच्छ समस्या है।

शुरुआत करने के लिए आपको टिप्पणियों और तार के बारे में चिंता करनी होगी। यदि आप नियमित अभिव्यक्ति का उपयोग करने वाली प्रोग्रामिंग भाषा पर यह जांचना चाहते हैं, तो यह आपकी खोज को फिर से कठिन बना देगा।

इसलिए इससे पहले कि मैं अंदर आ सकूं और आपके सवाल पर आपको कोई सलाह दूं, मुझे आपके समस्या क्षेत्र की सीमाएं जानने की जरूरत है। यदि आप यह गारंटी दे सकते हैं कि चिंता करने के लिए कोई तार, कोई टिप्पणी और कोई नियमित अभिव्यक्ति नहीं है - या अधिक उदारता से कोड में कहीं भी नहीं है कि कोष्ठक संभवतः उन उपयोगों के अलावा अन्य उपयोग किए जा सकते हैं जिनके लिए आप जाँच कर रहे हैं कि वे संतुलित हैं - यह होगा जीवन को बहुत सरल बनाओ।

उस भाषा को जानना, जिसे आप जांचना चाहते हैं, सहायक होगा।


अगर मैं परिकल्पना लेता हूं कि कोई शोर नहीं है, अर्थात सभी कोष्ठक उपयोगी कोष्ठक हैं, तो मेरी रणनीति पुनरावृत्ति होगी:

मैं बस सभी आंतरिक ब्रैकेट जोड़े को खोजूंगा और हटाऊंगा: जिनके अंदर कोई ब्रैकेट नहीं हैं। यह सबसे अच्छी तरह से सभी लाइनों को एक ही लंबी लाइन को ध्वस्त करके किया जाता है (और लाइन संदर्भ जोड़ने के लिए एक तंत्र ढूंढें, क्या आपको उस जानकारी को प्राप्त करने की आवश्यकता है)। इस मामले में खोज और प्रतिस्थापित बहुत सरल है:

इसके लिए एक सरणी चाहिए:

B["("]=")"; B["["]="]"; B["{"]="}"

और उन तत्वों के माध्यम से एक लूप:

for (b in B) {gsub("[" b "][^][(){}]*[" B[b] "]", "", $0)}

मेरी परीक्षा फ़ाइल इस प्रकार है:

#!/bin/awk

($1 == "PID") {
  fo (i=1; i<NF; i++)
  {
    F[$i] = i
  }
}

($1 + 0) > 0 {
  count("VIRT")
  count("RES")
  count("SHR")
  count("%MEM")
}

END {
  pintf "VIRT=\t%12d\nRES=\t%12d\nSHR=\t%12d\n%%MEM=\t%5.1f%%\n", C["VIRT"], C["RES"], C["SHR"], C["%MEM"]
}

function count(c[)
{
  f=F[c];

  if ($f ~ /m$/)
  {
    $f = ($f+0) * 1024
  }

  C[c]+=($f+0)
}

मेरी पूरी स्क्रिप्ट (बिना लाइन रेफरेंस के) इस प्रकार है:

cat test-file-for-brackets.txt | \
  tr -d '\r\n' | \
  awk \
  '
    BEGIN {
      B["("]=")";
      B["["]="]";
      B["{"]="}"
    }
    {
      m=1;
      while(m>0)
      {
        m=0;
        for (b in B)
        {
          m+=gsub("[" b "][^][(){}]*[" B[b] "]", "", $0)
        }
      };
      print
    }
  '

उस स्क्रिप्ट का आउटपुट ब्रैकेट्स के अंतरतम अवैध उपयोगों पर रुक जाता है। लेकिन सावधान रहें: 1 / यह स्क्रिप्ट टिप्पणियों, नियमित अभिव्यक्तियों या स्ट्रिंग्स में कोष्ठक के साथ काम नहीं करेगी, 2 / यह रिपोर्ट नहीं करता है कि मूल फ़ाइल में समस्या कहाँ स्थित है, 3 / हालांकि यह सभी संतुलित जोड़े को हटा देगा, जो कि अंतरतम पर रुक जाता है त्रुटि की स्थिति और सभी कोष्ठक कोष्ठक रखता है।

पॉइंट 3 / शायद एक शोषणकारी परिणाम है, हालाँकि मुझे आपके द्वारा बताए गए रिपोर्टिंग तंत्र के बारे में निश्चित नहीं है।

पॉइंट 2 / को लागू करना अपेक्षाकृत आसान है, लेकिन उत्पादन करने में कुछ मिनट से अधिक समय लगता है, इसलिए मैं इसका पता लगाने के लिए आपको छोड़ दूंगा।

बिंदु 1 / एक मुश्किल है, क्योंकि आप कभी-कभी नेस्टेड शुरुआत और अंत, या विशेष वर्णों के लिए विशेष उद्धरण नियमों के साथ प्रतिस्पर्धा के एक पूरे नए दायरे में प्रवेश करते हैं ...


1
धन्यवाद, आपने मुझे बचा लिया। एक 30k लाइन json फ़ाइल में एक बेमेल ब्रेस था।
I82Much
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.