ฉันมีไฟล์ที่มีชื่อไดเรกทอรี:
my_list.txt
:
/tmp
/var/tmp
ฉันต้องการตรวจสอบใน Bash ก่อนที่ฉันจะเพิ่มชื่อไดเรกทอรีหากชื่อนั้นมีอยู่แล้วในไฟล์
ฉันมีไฟล์ที่มีชื่อไดเรกทอรี:
my_list.txt
:
/tmp
/var/tmp
ฉันต้องการตรวจสอบใน Bash ก่อนที่ฉันจะเพิ่มชื่อไดเรกทอรีหากชื่อนั้นมีอยู่แล้วในไฟล์
คำตอบ:
grep -Fxq "$FILENAME" my_list.txt
สถานะการออกคือ 0 (จริง) หากพบชื่อ, 1 (เท็จ) หากไม่ใช่ดังนั้น:
if grep -Fxq "$FILENAME" my_list.txt
then
# code if found
else
# code if not found
fi
นี่คือส่วนที่เกี่ยวข้องของman page สำหรับgrep
:
grep [options] PATTERN [FILE...]
-F
,--fixed-strings
ตีความรูปแบบเป็นรายการของสตริงคงที่คั่นด้วยบรรทัดใหม่ใด ๆ ที่จะต้องจับคู่
-x
,--line-regexp
เลือกเฉพาะการแข่งขันที่ตรงกับทั้งเส้น
-q
,--quiet
,--silent
เงียบ; ห้ามเขียนอะไรไปยังเอาต์พุตมาตรฐาน ออกทันทีโดยมีสถานะเป็นศูนย์หากพบคู่ที่ตรงกันแม้ว่าตรวจพบข้อผิดพลาด ดูตัวเลือก
-s
หรือ--no-messages
ตามที่ระบุไว้อย่างถูกต้องในความคิดเห็นวิธีการดังกล่าวข้างต้นเงียบปฏิบัติกรณีข้อผิดพลาดราวกับว่าพบสตริง หากคุณต้องการจัดการข้อผิดพลาดในวิธีอื่นคุณจะต้องไม่ใช้-q
ตัวเลือกและตรวจหาข้อผิดพลาดตามสถานะการออก:
โดยปกติสถานะการออกคือ 0 หากพบบรรทัดที่เลือกและ 1 เป็นอย่างอื่น แต่สถานะการออกคือ 2 หากเกิดข้อผิดพลาดยกเว้นว่าจะใช้
-q
หรือ--quiet
หรือ--silent
ตัวเลือกและพบบรรทัดที่เลือก แต่โปรดทราบว่า POSIX เอกสารเท่านั้นสำหรับโปรแกรมเช่นgrep
,cmp
และdiff
ที่ออกจากสถานะในกรณีของข้อผิดพลาดจะสูงกว่า 1; ดังนั้นจึงแนะนำให้เลือกใช้ตรรกะที่ทดสอบเงื่อนไขทั่วไปนี้แทนความเสมอภาคที่เข้มงวดด้วย 2
เพื่อให้การปราบปรามการส่งออกตามปกติจากการที่คุณสามารถเปลี่ยนเส้นทางไปยังgrep
/dev/null
โปรดทราบว่าข้อผิดพลาดมาตรฐานยังคงไม่ถูกนำไปใช้ดังนั้นข้อความแสดงข้อผิดพลาดใด ๆ ที่grep
อาจพิมพ์จะจบลงที่คอนโซลตามที่คุณอาจต้องการ
ในการจัดการทั้งสามกรณีเราสามารถใช้case
คำสั่ง:
case `grep -Fx "$FILENAME" "$LIST" >/dev/null; echo $?` in
0)
# code if found
;;
1)
# code if not found
;;
*)
# code if an error occurred
;;
esac
$?
ออกจากสถานะล่าสุดส่วนใหญ่สามารถเข้าถึงได้โดยใช้ คุณยังสามารถใช้คำสั่ง grep ข้างif
คำสั่ง (ดังที่แสดงในคำตอบที่ปรับปรุงแล้ว)
grep -Fqx "$FILENAME"
และคุณไม่ต้องกังวลกับอักขระ regex ในเนื้อหาตัวแปรและคุณไม่ต้องใช้อักขระในสตริงการค้นหา
-q / --silent
มันจำเป็นหรือไม่ มันเท็จว่า "ดีทั้งหมด" เพื่อทุบตีแม้ว่าจะมีข้อผิดพลาดเกิดขึ้น ถ้าฉันได้รับอย่างถูกต้อง ดูเหมือนว่าแนวคิดที่มีข้อบกพร่องสำหรับกรณีนี้
เกี่ยวกับการแก้ปัญหาต่อไปนี้:
grep -Fxq "$FILENAME" my_list.txt
ในกรณีที่คุณสงสัย (เหมือนที่ฉันทำ) สิ่งที่-Fxq
เป็นภาษาอังกฤษธรรมดา:
F
: มีผลต่อวิธีการตีความแบบ (สตริงคงที่แทนที่จะเป็น regex)x
: จับคู่ทั้งบรรทัดq
: Shhhhh ... การพิมพ์ขั้นต่ำจากไฟล์ man:
-F, --fixed-strings
Interpret PATTERN as a list of fixed strings, separated by newlines, any of which is to be matched.
(-F is specified by POSIX.)
-x, --line-regexp
Select only those matches that exactly match the whole line. (-x is specified by POSIX.)
-q, --quiet, --silent
Quiet; do not write anything to standard output. Exit immediately with zero status if any match is
found, even if an error was detected. Also see the -s or --no-messages option. (-q is specified by
POSIX.)
สามวิธีในใจของฉัน:
1) การทดสอบสั้น ๆ สำหรับชื่อในพา ธ (ฉันไม่แน่ใจว่านี่อาจเป็นกรณีของคุณ)
ls -a "path" | grep "name"
2) การทดสอบสั้น ๆ สำหรับสตริงในไฟล์
grep -R "string" "filepath"
3) สคริปต์ทุบตีอีกต่อไปโดยใช้ regex:
#!/bin/bash
declare file="content.txt"
declare regex="\s+string\s+"
declare file_content=$( cat "${file}" )
if [[ " $file_content " =~ $regex ]] # please note the space before and after the file content
then
echo "found"
else
echo "not found"
fi
exit
สิ่งนี้น่าจะเร็วกว่าถ้าคุณต้องทดสอบหลาย ๆ สตริงในเนื้อหาไฟล์โดยใช้การวนซ้ำตัวอย่างเช่นการเปลี่ยน regex ที่ cicle ใด ๆ
วิธีที่ง่ายกว่า:
if grep "$filename" my_list.txt > /dev/null
then
... found
else
... not found
fi
เคล็ดลับ: ส่งไปยัง/dev/null
หากคุณต้องการสถานะการออกของคำสั่ง แต่จะไม่ส่งออก
-q
ซึ่งเหมือนกับ--quiet
:)
-q
คำตอบที่ดีที่สุดที่นี่และเป็นที่สี่ ไม่มีความยุติธรรมในโลกนี้
วิธีที่ง่ายที่สุดและง่ายที่สุดคือ:
isInFile=$(cat file.txt | grep -c "string")
if [ $isInFile -eq 0 ]; then
#string not contained in file
else
#string is in file at least once
fi
grep -c จะคืนค่าจำนวนสตริงที่เกิดขึ้นในไฟล์
หากฉันเข้าใจคำถามของคุณถูกต้องสิ่งนี้ควรทำในสิ่งที่คุณต้องการ
ในหนึ่งบรรทัด :check="/tmp/newdirectory"; [[ -n $(grep "^$check\$" my_list.txt) ]] && echo "dir already listed" || echo "$check" >> my_list.txt
grep -q
และเรียก grep โดยตรงจากif
ที่ Thomas ทำในคำตอบของเขา นอกจากนี้คำถามไม่ได้รวมการตรวจสอบว่ามีไดเรกทอรีอยู่ก่อนที่จะเพิ่มลงในรายการหรือไม่ (อาจเป็นรายการของไดเรกทอรีที่ถูกลบหลังจากทั้งหมด)
หากคุณต้องการตรวจสอบการมีอยู่ของหนึ่งบรรทัดคุณไม่จำเป็นต้องสร้างไฟล์ เช่น,
if grep -xq "LINE_TO_BE_MATCHED" FILE_TO_LOOK_IN ; then
# code for if it exists
else
# code for if it does not exist
fi
รุ่นของฉันใช้ fgrep
FOUND=`fgrep -c "FOUND" $VALIDATION_FILE`
if [ $FOUND -eq 0 ]; then
echo "Not able to find"
else
echo "able to find"
fi
-c
ตัวเลือกในfgrep --help
grep -E "(string)" /path/to/file || echo "no match found"
ตัวเลือก - E ทำให้ grep ใช้การแสดงออกปกติ
วิธีแก้ปัญหาของ @ Thomas ไม่ได้ผลสำหรับฉันด้วยเหตุผลบางอย่าง แต่ฉันมีสตริงที่ยาวกว่าด้วยอักขระพิเศษและช่องว่างดังนั้นฉันจึงเปลี่ยนพารามิเตอร์ดังนี้:
if grep -Fxq 'string you want to find' "/path/to/file"; then
echo "Found"
else
echo "Not found"
fi
หวังว่าจะช่วยใครซักคน
วิธีแก้ปัญหา grep-less เหมาะกับฉัน:
MY_LIST=$( cat /path/to/my_list.txt )
if [[ "${MY_LIST}" == *"${NEW_DIRECTORY_NAME}"* ]]; then
echo "It's there!"
else
echo "its not there"
fi
grep -q
อธิบายไว้ในคำตอบที่ยอมรับได้เป็นวิธีที่มีประสิทธิภาพที่สุด
grep -Fxq "String to be found" | ls -a
if grep -q "$Filename$" my_list.txt
then
echo "exist"
else
echo "not exist"
fi