केवल उन फ़ाइलों में खोजें जो ack के साथ एक पैटर्न से मेल खाती हैं


49

Ack केवल उन फ़ाइलों के माध्यम से खोज कर सकता है जो एक विशिष्ट 'ग्लोब' पैटर्न से मेल खाती हैं (जैसे: "बार * .c" नाम की सभी फाइलों में foo के लिए खोज। आदेश

ack foo "bar*.c"

केवल वर्तमान निर्देशिका में काम करता है।

नोट: मुझे पता है कि यह खोज के साथ संभव है -सेक्स:

find . -name "bar*.c" -type f -exec ack foo {} + 

लेकिन मैं एक छोटी और सरल ack कमांड पसंद करूंगा, क्योंकि मैं संस्करण नियंत्रण निर्देशिकाओं को नहीं छोड़ता।


2
मुझे समझ में नहीं आ रहा है, क्या गलत है find . -name "bar*.c" -exec ack foo {} \;? इसमें कुछ खास नहीं है grep, आप फाइंड के साथ किसी भी कमांड का उपयोग कर सकते हैं -exec
terdon

1
@terdon भी संस्करण नियंत्रण निर्देशिकाओं के माध्यम से खोज करता है और मुझे वह नहीं चाहिए।
संकलन

2
फिर कृपया अपने प्रश्न को संपादित करें और उन सीमाओं की व्याख्या करें जिन्हें आपको काम करने की आवश्यकता है।
terdon

जवाबों:


28

निर्देशिका खोज रहे हैं

मैन पेज में दिखाए गए सिनॉप्सिस के आधार पर मैं कहूंगा कि यह एक निर्देशिका को संसाधित कर सकता है, लेकिन स्विच को देखते हुए यह एक पैटर्न के आधार पर सिर्फ एक फ़ाइल के लिए नहीं देख सकता है। उसके लिए आपको सूची तैयार करनी होगी find। आदेश ackमें विकल्प शामिल होता है --files-from=FILEताकि इसे फाइलों की सूची से खिलाया जा सके find

सार

       ack [options] PATTERN [FILE...]
       ack -f [options] [DIRECTORY...]

प्रयोग

   --files-from=FILE
       The list of files to be searched is specified in FILE.  The list of
       files are separated by newlines.  If FILE is "-", the list is
       loaded from standard input.

एक --ignore-file=विकल्प है जो आपको वह दे सकता है जो आप चाहते हैं लेकिन वास्तव में उपयोग करने के लिए थोड़ा दर्द लगता है।

   --ignore-file=FILTERTYPE:FILTERARGS
       Ignore files matching FILTERTYPE:FILTERARGS.  The filters are
       specified identically to file type filters as seen in "Defining
       your own types".

विशिष्ट प्रकार की फ़ाइलों की खोज करना

केवल एक और तरीका है जिसके माध्यम से मैं ackइसके --typeस्विच का उपयोग कर सकता हूं।

   --type=[no]TYPE
       Specify the types of files to include or exclude from a search.
       TYPE is a filetype, like perl or xml.  --type=perl can also be
       specified as --perl, and --type=noperl can be done as --noperl.

       If a file is of both type "foo" and "bar", specifying --foo and
       --nobar will exclude the file, because an exclusion takes
       precedence over an inclusion.

यह देखने के लिए कि कौन से प्रकार उपलब्ध हैं:

$ ack --help-types | grep -E "perl|cpp"

प्रारूप। उदाहरण के लिए, दोनों - टाइप = पर्ल और - एपर्ल काम। - [कोई] सीपीसी .सीपीसी .सीपीसी। एमएक्स .एचपी .एचपी .एचएच .एच। एक्सएक्सएक्स - [नहीं] ओब्जेक्प .एमएम .एच। - [नहीं] पर्ल। पीपीएम। पीपीओ। टीपीएस। पहली पंक्ति /^# से मेल खाती है!

उदाहरण

फ़ाइल नाम (* .pm, * .pl, * .t और * .pod) और शबंग रेखा दोनों के आधार पर सभी पर्ल फाइलें खोजें।

$ ack -f --type perl 
examples/iwatch/iwatch/iwatch
examples/nytprof_perl/bad.pl

सभी C ++ फ़ाइलें खोजें:

$ ack -f --type=cpp
Shared/Scanner.h
Shared/Sorter.h
Shared/DicomHelper.cpp
Shared/DicomDeviationWriter.h

बार * .c में फू के लिए खोज करना

तो फिर आप जो चाहते हैं उसे कैसे पूरा कर सकते हैं? वैसे आपको इसका उपयोग findकरने की संभावना होगी :

$ find adir -iname "bar*.c" | ack --files-from=- foo
adir/bar1.c
1:foo
2:foo

adir/dir1/bar1.c
1:foo
2:foo

आप उन ackफ़ाइलों की खोज करने की क्षमता का भी उपयोग कर सकते हैं जो उनके फ़ाइलनाम (उपयोग -g <pattern>) में दिए गए पैटर्न से मेल खाती हैं , और फिर इस सूची को ackउपयोग करने के दूसरे आह्वान पर -xया पास करें --files-from=-

का उपयोग कर -x:

$ ack -g '\bbar.*.c$' | ack -x foo
bar1.c
1:foo
2:foo

dir1/bar1.c
1:foo
2:foo

का उपयोग कर -files-from=-:

$ ack -g '\bbar.*.c$' | ack --files-from=- foo
bar1.c
1:foo
2:foo

dir1/bar1.c
1:foo
2:foo

या तो मामले में हम उन फ़ाइलनामों का मिलान कर रहे हैं, जिन्हें आप इस regex का उपयोग करना चाहते हैं:

\bbar.*.c$

यह उन फ़ाइलों से मेल खाता है जिनका नाम है bar.*cऔर .cलाइन एंकर के अंत का उपयोग करने के बाद समाप्त होता है $। हम यह भी सुनिश्चित करने के लिए देखते हैं कि नामों का उपयोग करने के लिए एक सीमा चरित्र है \b। यह उन फ़ाइलों के लिए विफल हो जाएगा जिनमें सीमा वर्ण होते हैं जैसे कि $bar.cया %bar.cउदाहरण के लिए।


1
यह मेरे प्रश्न का उत्तर नहीं देता है ("बार * .c" नाम की सभी फाइलों में foo की खोज करें)
compie

1
@ कॉम - यह इस अर्थ में करता है कि मैं आपको दिखा रहा हूं कि आप जिस फाइल को चाहते हैं उसका एक टुकड़ा कैसे प्राप्त करें। cppफ़ाइलों की खोज करने के लिए ack --type=cpp <string>ackहालांकि इस सब पर अधिक के लिए मैन पेज देखें । लेकिन जो मैं मूल रूप से आपको बता रहा हूं, वह यह है कि आप अपने ackइच्छित तरीके का उपयोग करके खोज नहीं कर सकते ।
slm

1
इसलिए यह इस अर्थ में उत्तर देता है कि यह दिखाता है कि ackजो पूछा गया था वह नहीं कर सकता है।
xealits

@xealits - यह भाग इसका उत्तर देता है: बार * .c में फू के लिए खोज करना find adir -iname "bar*.c" | ack --files-from=- foo । या, यदि आप केवल एक फ़ाइल चाहते हैं:echo "barBaz.c" | ack --files-from=- foo
अलेक्जेंडरबर्ड

2
tldr; ack -g '\bbar.*.c$' | ack -x foo
चिम

14

यदि फ़ाइल प्रकार ज्ञात है, तो यह आसान है, और ack बहुत प्रकार की फ़ाइल जानता है। इसलिए, उदाहरण के लिए, आप केवल C फ़ाइलों में खोज करना चाहते हैं, जो आप कर सकते हैं:

ack --cc 'string'

लेकिन अगर यह ज्ञात एक्सटेंशन में से एक नहीं है, तो आपको अपने प्रकार को परिभाषित करने की आवश्यकता है। यह काम करना चाहिए:

ack --type-set barc:match:/bar.+\.c/ --barc 'string'

ध्यान दें कि आपको दोनों की आवश्यकता है - टाइप-सेट और --barc।

(एंडी को धन्यवाद, जिन्होंने मेलिंग सूची में इसके साथ मदद की।)


1
ठीक है जो काम करता है लेकिन खोज और 'ax -x' का उपयोग करना सरल है। मुझे लगता है कि मैं इसके साथ रहूंगा।
संकलन

डॉक्स के लिए एक लिंक जोड़ना यहाँ मददगार होगा। man ackवास्तव में मदद नहीं करता है और ccजब मुझे लगता है कि नहीं है।
YPCrumble

ack --help = प्रकार वहाँ कुछ भी है जो मैं वहाँ के बारे में सोच सकता हूँ। मैं ज्यादातर इसका इस्तेमाल पायथन और एडा के लिए करता हूं।
डेविड बॉस्टन

6

"एके 2 में नया क्या है?" http://beyondgrep.com/ack-2.0/

ack 2.0 के साथ, आप नए -x का उपयोग पाइप फाइलनाम को ack के एक मंगलाचरण से दूसरे में करने के लिए कर सकते हैं।

ack2 -g -i filepattern | ack2 -x -w searchpattern

केवल मैं इसे काम नहीं कर सकता:

% ack -g "*bar*.c"
Invalid regex '*bar*.c':
Quantifier follows nothing in regex; marked by <-- HERE in m/* <-- HERE bar*.c/ at ack line 314.

इस प्रकार, ऐसा लगता है कि मुझे एक regex की आवश्यकता है, जबकि मुझे 'ग्लोब' शैली का विकल्प चाहिए ...


2
हां, -gरेगेक्स लेता है, ग्लोब नहीं। आप के रूप में अपने regex लिख सकता है .*bar.*\.c$
एंडी लेस्टर

2
@AndyLester पुष्टि करने के लिए धन्यवाद। क्या आपको ack के लिए 'glob' विकल्प का विचार पसंद है?
अपराह्न

3

यह सबसे तेज़ और सबसे सुरक्षित प्रतीत होगा:

find . -name '*.c' | ack -x 'some string'

-x STDIN से खोज करने के लिए फ़ाइलों की सूची पढ़ें।

हालाँकि, यदि फ़ाइल आपके locateडेटाबेस में होने की संभावना है , तो यह और भी तेज होगा:

locate --basename '*.c' | ack -x 'some thing'

पता लगाएँ कि पुराने स्कूल के नियमित अभिव्यक्ति को स्वीकार कर सकते हैं, थोड़ा दर्दनाक है, लेकिन अगर आप cफ़ाइलों की तलाश कर रहे हैं , तो इसकी आवश्यकता हो सकती है। जैसे

locate --basename --regexp '\.\(c\|cpp\|h\|hpp\|cc\)$' |
    ack -x 'some thing'

यह सिर्फ अनुवाद करता है: "सभी फ़ाइलनाम खोजें जो सी, सीपी, एच, एचपीपी या सीसी में समाप्त होते हैं।"


2

Ack ग्लोब स्टाइल फ़ाइल चयन का समर्थन नहीं करता है। चूंकि मुझे वास्तव में यह याद है इसलिए मैंने एक छोटी सी शेल स्क्रिप्ट ackg बनाई :

#!/bin/sh
# 'glob' support for ack
find -name "$2" -type f -exec ack "$1" {} +

अब आप कमांड का उपयोग कर सकते हैं:

ackg foo "bar*.c"

लेकिन ध्यान दें: यह दुर्भाग्य से संस्करण नियंत्रण dirs (जैसे: .git) में भी खोज करेगा।


2

यह एजी के -Gविकल्प के साथ किया जा सकता है , सिल्वर खोजकर्ता (ack-grep का एक बढ़ाया क्लोन)।

$ echo foo > bar_wanted.c
$ echo foo > unwanted.c
$ ag -G "bar.*\.c" foo
bar_wanted.c
1:foo

टिप्पणियाँ:

  • agPCRE नियमित अभिव्यक्ति सिंटैक्स का उपयोग करता है , इसलिए regexp bar.*\.cइसके बजाय होना चाहिए bar*.c
  • -Gविकल्प, खोज पद पूर्व में होना करने के लिए के रूप में उस के बाद कुछ भी एक फ़ाइल नाम के रूप में व्याख्या की है की जरूरत है।

1

क्या आप केवल एक निश्चित पैटर्न चाहते हैं, या क्या आप केवल सी स्रोत फ़ाइलें चाहते हैं?

यदि आप सभी C फाइलें चाहते हैं, तो उपयोग करें

ack --cc foo

यदि आप चाहते हैं कि सभी C फाइलें और C C हेडर फाइलें उपयोग न करें

ack --cc --no-hh foo

1

@chim का उत्तर सबसे अच्छा है, लेकिन इसकी टिप्पणी के रूप में लिखा गया है इसलिए मैं एक औपचारिक उत्तर के रूप में दोहरा रहा हूं ...

ack -g '\bbar.*.c$' | ack -x foo

मैं इस तथ्य को पसंद करता हूं कि आपका मार्ग पुन: जुड़ सकता है ...


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