How to manipulate a string with the grep command? [duplicate] - bash

This question already has answers here:
How can I remove the extension of a filename in a shell script?
(15 answers)
Closed 11 months ago.
I have a filename with the format yyyymmdd.txt. How can I output only yyyymmdd without the .txt extension?
Example
20220414.txt (before output)
20220414 (after the output)

basename has an option to remove a suffix:
basename -s .txt 20220414.txt
gives:
20220414
Or, if your filename is stored in a variable, bash can help:
a=20220414.txt
echo ${a%.*}
gives:
20220414

You can user awk with flag -F to specify the separator . and then print the first part with $1
echo "20220414.txt" | awk -F "." ' {print $1}'
output
20220414

grep doesn't manipulate anything, it shows what you have in a file. So, you can't modify that file using grep, but you can modify what it shows, using the -o switch, as you can see here:
Prompt> echo "20220414.txt" | grep -o "[0-9]*"
20220414
The [0-9]* means "a list of integers, going from character '0' to character '9'.

Related

Find all occurrences of a word in .txt files with GIT Bash on Windows [duplicate]

This question already has an answer here:
Using regex in Grep for Windows command line
(1 answer)
Closed 2 years ago.
Trying to find all occurrences of a word in a range of different .txt files in a directory.
I'm looking for commands that will give me an exact count if possible.
so far I have tried:
$ grep -w 'string' *
and:
$ grep --include=\*.{txt} -rnw desktop/testfiles/ -e "string"
The first outputs its entire contents and the second doesn't seem to do anything.
Any ideas?
simply :
grep -w "string" *.txt | wc -l
also GNU awk allows it to be done in single command
awk -v w="string" '$1==w{n++} END{print n}' RS=' |\n' *.txt

Extract specific string from line with standard grep,egrep or awk

i'm trying to extract a specific string from a grep output
uci show minidlna
produces a large list
.
.
.
minidlna.config.enabled='1'
minidlna.config.db_dir='/mnt/sda1/usb/db'
minidlna.config.enable_tivo='1'
minidlna.config.wide_links='1'
.
.
.
so i tried to narrow down what i wanted by running
uci show minidlna | grep -oE '\bdb_dir=\S+'
this narrows the output to
db_dir='/mnt/sda1/usb/db'
what i want is to output only
/mnt/sda1/usb/db
without the quotes and without the starting "db_dir" so i can run rm /mnt/sda1/usb/db/file.db
i've used the answers found here
How to extract string following a pattern with grep, regex or perl
and that's as close as i got.
EDIT: after using Ed Morton's awk command i needed to pass the output to rm command.
i used:
| ( read DB; (rm $DB/files.db) .
read DB passes the output into the vairable DB.
(...) combines commands.
rm $DB/files.db deletes the the file files.db.
Is this what you're trying to do?
$ awk -F"'" '/db_dir/{print $2}' file
/mnt/sda1/usb/db
That will work in any awk in any shell on every UNIX box.
If that's not what you want then edit your question to clarify your requirements and post more truly representative sample input/output.
Using sed with some effort to avoid single quotes:
sed -n 's/^minidlna.config.db_dir=\s*\S\(\S*\)\S\s*$/\1/p' input
Well, so you end up having a string like db_dir='/mnt/sda1/usb/db'.
I would first remove the quotes by piping this to
.... | tr -d "'"
Now you end up with a string like db_dir=/mnt/sda1/usb/db.
Say you have this string stored in a variable named confstr, then
${confstr##*=}
gives you just /mnt/sda1/usb/db, since *= denotes everything from the start to the equal sign, and ## denotes removal.
I would do this:
Once you either extracted your line about into file.txt (or pipe it into this command), split the fields using the quote character. Use printf to generate the rm command and pass this into bash to execute.
$ awk -F"'" '{printf "rm %s.db/file.db\n", $2}' file.txt | bash
rm: /mnt/sda1/usb/db.db/file.db: No such file or directory
With your original command:
$ uci show minidlna | grep -oE '\bdb_dir=\S+' | \
awk -F"'" '{printf "rm %s.db/file.db\n", $2}' | bash

How can I delete empty line from my ouput by grep? [duplicate]

This question already has answers here:
Remove empty lines in a text file via grep
(11 answers)
Closed 4 years ago.
Exists way to remove empty lines with cat myfile | grep -w #something ?
I looking for simple way for remove empty lines from my output like in the way the presented above.
This really belongs on the codegolfing stackexchange because it's not related to how anyone would ever write a script. However, you can do it like this:
cat myfile | grep -w '.*..*'
It's equivalent to the more canonical grep ., but adds explicit .*s on either side so that it will always match the complete line, thereby satisfying the word boundary conditions imposed by -w
You can pipe your output to awk to easily remove empty lines
cat myfile | grep -w #something | awk NF
EDIT: so... you just want cat myfile | awk NF?
if you have to use grep, you can do grep myfile -v '^[[:blank:]]*$'

Searching a file name in file using SHELL SCRIPT [duplicate]

This question already has answers here:
Find lines from a file which are not present in another file [duplicate]
(4 answers)
Closed 8 years ago.
I will fetch the file names from the file say: FILE_A, and will search these file names in another file say: File_B Using the script say: script.sh
I want to print those file names which are not present in a file say: FILE_B.
I use the code but it didn't work.
Code in the script->script.sh is as follows:
#!/bin/bash
while read line
do
grep -v "$line" FILE_B
done<FILE_A
please help me. why it is not working and what is the solution of it?
grep can read its input from a file; no need for a loop.
grep -Fxvf FILE_A FILE_B
The -F option specifies that the input is literal strings, not regular expressions. Otherwise an input which contains regex metacharacters would not match itself; or not only itself. For example, the regular expression a.c matches "aac", "abc", etc.
The -x option requires a full-line match. Otherwise, the input "bc" would match on any line containing it as a substring, such as "abcd".
The -v option says to print non-matching lines instead of matching.
Finally, the lowercase -f option specifies a file name as its argument to use as input for the patterns to match.
comm is good for this, but it requires the input files to be sorted. If that's not a problem:
# lines in FILE_A that are not in FILE_B
comm -23 <(sort FILE_A) <(sort FILE_B)
No extra linefeed between while and do
grep -v expr file will
print all lines of those files, not containing expr. What you want, is just the result whether it's found or not. You need to test the
exit state.
Try:
#!/bin/bash
while read line
do
grep -q "$line" FILE_B || echo "$line"
done<FILE_A
grep returns exit 0 if a line was found. The || concatenation with echo means: execute echo when exit state != 0- i.e. when $line was not found.
This script works but does not print what you want. For each filename in FILE_A it prints all the OTHER filenames in FILE_B. Instead you should print the filename yourself if grep does not find it:
while read line
do
grep "$line" FILE_B >/dev/null || echo "$line"
done <FILE_A
Use this instead
#!/bin/bash
while read line
do
if grep -qw $line "file_B"
then
echo $line
fi
done < file_A

Print everything on line after match [duplicate]

This question already has answers here:
Get string after character [duplicate]
(5 answers)
Closed 7 years ago.
I have an large textfile that contains an unique string in the middle. What i want to do is to print everything AFTER the string by using grep.
cat textfile | grep "target_string"
This highlights target_string but prints the whole file
cat textfile | grep -o "target_string"
This prints only target_string
cat textfile | grep -o "target_string*"
This prints only target_string
How can i print everything after target_string and nothing before?
Strangely, the accepted answer printed out the whole line, where I just wanted all the info after the target string. This worked for me:
sed -n 's/target_string//p' filename
Adapted from this post
With GNU grep, try -B0 -A999999999 or similar. A better choice might be awk:
awk '/target_string/ {seen = 1}
seen {print}'
If (your problem specification is slightly unclear) you don't also need to print the matching line, sed is even shorter:
sed '1,/target_string/d'
You forgot the '.':
cat textfile | grep -o "target_string.*"
This will print everything after each match, on that same line only:
perl -lne 'print $1 if /target_string(.*)/' textfile
This will do the same, except it will also print all subsequent lines:
perl -lne 'if ($found){print} else{if (/target_string(.*)/){print $1; $found++}}' textfile

Resources