How to find a file and delete containing some string in the body using awk command from multiple files?

萝らか妹 提交于 2020-06-22 04:39:30

问题


I have multiple files in the file directory Record:

Record
   1.txt
   2.txt
   3.txt

The file 2.txt contains a string abcd in the second column of the first line. How can I print all the contents in 2.txt? How can I delete the file 2.txt?

I used awk to print all the contents in that file but it only prints that line.

I used find command to store the file name in the file.txt folder but it gives me an error.

rm -rf Record
mkdir Record
cd Record
echo f1
touch 1.txt
echo author: efg   > 1.txt
echo title: hijk  >> 1.txt
echo pages: 1990  >> 1.txt
echo year: 1890  >> 1.txt
touch 2.txt
echo author: abcd > 2.txt
echo author: lmno >> 2.txt
echo title: pqrs >> 2.txt
echo pages: 354 >> 2.txt
echo year:  1970 >> 2.txt
touch 3.txt
echo author: aklj > 3.txt
echo title: dban  >> 3.txt
echo pages: 876  >> 3.txt
echo year: 1860  >> 3.txt
cd ..
adress=./Record/*.txt
sfind=abcd
  awk ' BEGIN { sfind = ENVIRON["sfind"] }
    FNR == 1 { secondPass = seen[FILENAME]++ }
    secondPass { print FILENAME, $0; next }
    index($2,sfind) {
        ARGV[ARGC] = FILENAME
        ARGC++
        nextfile       
    }
'
$adress

回答1:


sfind='abcd' awk '
    BEGIN { sfind = ENVIRON["sfind"] }
    FNR == 1 { secondPass = seen[FILENAME]++ }
    secondPass { print FILENAME, $0; next }
    index($2,sfind) {
        ARGV[ARGC++] = FILENAME
        nextfile        # for efficiency if using GNU gawk.
    }
' ./Record/*.txt

The above makes 2 passes of the input files - the first pass to identify those that contain the value of the string stored in sfind in $2 and add them back into the and of ARGV[] so they'll be processed again later, the second to print the contents of those files identified on the first pass. If you don't want the input file name printed at the start of each output line then just change print FILENAME, $0 to print.

The above will work for any number of matches in any number of files (0, 1, 2, whatever), for any file names, even if they contain spaces, globbing characters, etc., and for any characters in sfind including backslash escapes and regexp metcharacters like . or *.

The above does partial string matching. Here are your options:

  • Partial string: index($2,sfind) (as shown)
  • Full field string: $2 == sfind
  • Partial regexp: $2 ~ sfind
  • Full field regexp: $2 ~ ("^" sfind "$")

Full word matching gets trickier, depends on your definition of a "word", and can be served by implementation-specific constructs so I'll leave that out unless you need it.




回答2:


Using GNU grep:

cat "$(grep -l abcd  *.txt | head -n 1)"

...or in long options form:

cat "$(grep --files-with-matches abcd  *.txt | head -n 1)"

To print the file name first, do:

n="$(grep -l abcd  *.txt | head -n 1)"
echo "-------- $n -------- "
cat "$n"


来源:https://stackoverflow.com/questions/62303150/how-to-find-a-file-and-delete-containing-some-string-in-the-body-using-awk-comma

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!