问题
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