Grep exact match "/etc" - search

I would like to make an exact search of the string /etc, in the next file:
-14: _etcrpm /etc/rpm
-14: _nssdb_path /etc/pki/nssdb
-14: _rpmds_ldconfig_cache /etc/ld.so.cache
-14: _sysconfdir /etc
-DKDE_DISTRIBUTION_TEXT="%(cat /etc/mandriva-release)" \
-14: distepoch %(sed -e 's#.*release\ \(\S*\).*#\1#' /etc/release)
-14: distro_class %(. /etc/sysconfig/system; echo $META_CLASS)
I would like that in the output of grep, appears the line that contains only "/etc"
-14: _sysconfdir /etc
Can somebody help me with that?
Thank you

This should work:
grep -P "(?<=\s)/etc(?=\s|$)" file
Or:
grep -E "\s/etc(\s|$)" file
Or:
grep "[[:space:]]/etc\([[:space:]]\|$\)" file
Output:
-14: _sysconfdir /etc
-P is for Perl regex.
-E is for extended regex.

In this case, you could use awk to check if the last word is "/etc"
awk '$NF == "/etc" file

Related

How to apply my sed command to some lines of all my files?

I've 95 files that looks like :
2019-10-29-18-00/dev/xx;512.00;0.4;/var/x/xx/xxx
2019-10-29-18-00/dev/xx;512.00;0.68;/xx
2019-10-29-18-00/dev/xx;512.00;1.84;/xx/xx/xx
2019-10-29-18-00/dev/xx;512.00;80.08;/opt/xx/x
2019-10-29-18-00/dev/xx;20480.00;83.44;/var/x/x
2019-10-29-18-00/dev/xx;3584.00;840.43;/var/xx/x
2019-10-30-00-00/dev/xx;2048.00;411.59;/
2019-10-30-00-00/dev/xx;7168.00;6168.09;/usr
2019-10-30-00-00/dev/xx;3072.00;1036.1;/var
2019-10-30-00-00/dev/xx;5120.00;348.72;/tmp
2019-10-30-00-00/dev/xx;20480.00;2033.19;/home
2019-10-30-12-00;/dev/xx;5120.00;348.72;/tmp
2019-10-30-12-00;/dev/hd1;20480.00;2037.62;/home
2019-10-30-12-00;/dev/xx;512.00;0.43;/xx
2019-10-30-12-00;/dev/xx;3584.00;794.39;/xx
2019-10-30-12-00;/dev/xx;512.00;0.4;/var/xx/xx/xx
2019-10-30-12-00;/dev/xx;512.00;0.68;/xx
2019-10-30-12-00;/dev/xx;512.00;1.84;/var/xx/xx
2019-10-30-12-00;/dev/xx;512.00;80.08;/opt/xx/x
2019-10-30-12-00;/dev/xx;20480.00;83.44;/var/xx/xx
2019-10-30-12-00;/dev/x;3584.00;840.43;/var/xx/xx
For some lines I've 2019-10-29-18-00/dev and for some other lines, I've 2019-10-30-12-00;/dev/
I want to add the ; before the /dev/ where it is missing, so for that I use this sed command :
sed 's/\/dev/\;\/dev/'
But How I can apply this command for each lines where the ; is missing ? I try this :
for i in $(cat /home/xxx/xxx/xxx/*.txt | grep -e "00/dev/")
do
sed 's/\/dev/\;\/dev/' $i > $i
done
But it doesn't work... Can you help me ?
Could you please try following with GNU awkif you are ok with it.
awk -i inplace '/00\/dev\//{gsub(/00\/dev\//,"/00;/dev/")} 1' *.txt
sed solution: Tested with GNU sed for few files and it worked fine.
sed -i.bak '/00\/dev/s/00\/dev/00\;\/dev/g' *.txt
This might work for you (GNU sed & parallel):
parallel -q sed -i 's#;*/dev#;/dev#' ::: *.txt
or if you prefer:
sed -i 's#;*/dev#;/dev#' *.txt
Ignore lines with ;/dev.
sed '/;\/dev/{p;d}; s^/dev^;/dev^'
The /;\/dev/ check if the line has ;/dev. If it has ;/dev do: p - print the current line and d - start from the beginning.
You can use any character with s command in sed. Also, there is no need in escaping \;, just ;.
How I can apply this command for each lines where the ; is missing ? I try this
Don't edit the same file redirecting to the same file $i > $i. Think about it. How can you re-write and read from the same file at the same time? You can't, the resulting file will be in most cases empty, as the > $i will "execute" first making the file empty, then sed $i will start running and it will read an empty file. Use a temporary file sed ... "$i" > temp.txt; mv temp.txt "$i" or use gnu extension -i sed option to edit in place.
What you want to do really is:
grep -l '00/dev/' /home/xxx/xxx/xxx/*.txt |
xargs -n1 sed -i '/;\/dev/{p;d}; s^/dev^;/dev^'
grep -l prints list of files that match the pattern, then xargs for each single one -n1 of the files executes sed which -i edits files in place.
grep for filtering can be eliminated in your case, we can accomplish the task with a single sed command:
for f in $(cat /home/xxx/xxx/xxx/*.txt)
do
[[ -f "$f" ]] && sed -Ei '/00\/dev/ s/([^;])(\/dev)/\1;\2/' "$f"
done
The easiest way would be to adjust your regex so that it's looking a bit wider than '/dev/', e.g.
sed -i -E 's|([0-9])/dev|\1;/dev|'
(note that I'm taking advantage of sed's flexible approach to delimiters on substitute. Also, -E changes the group syntax)
Alternatively, sed lets you filter which lines it handles:
sed -i '/[0-9]\/dev/ s/\/dev/;/dev/'
This uses the same substitution you already have but only applied on lines that match the filter regex

Exclude smililar string while using sed

I have a some scripts into a directory and this directory containing other folders also. Which ever script are residing in my first (parent) directory I want to replace all 'dev' string into prod. but in some of the script I am nullifying the out by using dev/null . I don't want to change this as prod/null.
I am replacing all other 'dev' using below command.
grep -rl dev somedir|xargs sed -i 's/dev/prod/g'
Please let me know if there is any way to exclude changing dev/null to prod/null
Thanks.
If each entry in grep -r1 dev somedir is separated by a newline, you can use this
grep -rl dev somedir | grep -v "dev/null" | xargs sed -i 's/dev/prod/g'
It is possible to replace /dev/null to some other string (i.e. /xxx/null) before doing dev -> prog substitution and change it to /dev/null later.
grep -rl dev somedir|xargs sed -i -e 's!/dev/null!/xxx/null!g' -e 's/dev/prod/g' -e 's!/xxx/null!/dev/null!g'

Check if filename characters match outside of whitelist

In bash I'd like to test a number of directories if they contain filenames outside of what I have whitelisted:
[a-z]
[A-Z]
[0-9]
[+-_ßäöüÄÖÜ.,]
[ ]
(ie. one space is ok, two or more in a row would not).
Trying
$ ls my/dir/ |grep --color=always -v [a][b][c][d][e][f][g][h][i][j][k][l][m][n][o][p][q][r][s][t][u][v][w][x][y][z][A][B][C][D][E][F][G][H][I][J][K][L][M][N][O][P][Q][R][S][T][U][V][W][X][Y][Z][0][1][2][3][4][5][6][7][8][9]
yields all files, even the one containing a # character for testing.
So does the "shorthand" of
$ ls my/dir/ |grep --color=always -v [a-zA-Z0-9]
(and yes, I know I'd have to include the [+-_ßäöüÄÖÜ., ] characters into this later).
I have tried using diff for this:
$ diff -y <(ls -1 my/dir/) <(ls -1 /my/dir/|tr -cd '[a-zA-Z0-9\n\r \-\.\,]')|grep --color=never '|'|cut -d "|" -f 1
which outputs the filenames which are outside of my tr list:
A File Containing Some Rainbo#ws.wav
But this seems rather clumsy... Any ideas for something, well, nicer?
$ find -name '*[^a-zA-Z0-9+\-_ßäöüÄÖÜ., ]*' -o -name '* *'
See man find. The -regex and -maxdepth options might also be interesting to you.
PS: Don't parse the output of ls.
Something to get you started:
#!/bin/bash
regex='^[a-zA-Z0-9.]+$'
while read line
do
if ! [[ $(basename "$line") =~ $regex ]]
then
echo $line
fi
done < <(find . -type f)
$ ls my/dir/ |grep --color=always -v [a][b][c][d][e][f][g][h][i][j][k][l][m][n][o][p][q][r][s][t][u][v][w][x][y][z][A][B][C][D][E][F][G][H][I][J][K][L][M][N][O][P][Q][R][S][T][U][V][W][X][Y][Z][0][1][2][3][4][5][6][7][8][9]
The above line will look for file names that don't contain the character sequence abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789, which is why it matches so many files.
try
$ ls my/dir/ |grep --color=always -v [^a-zA-Z0-9+-_ßäöüÄÖÜ. ]
$ ls my/dir/ |grep --color=always " "
The first line looks for files that contain other characters than the white-listed ones.
The second line looks for files that contain double space.

Replace string using grep and sed

I have bunch of files in a directory,
I need to change prefix of lines in file like "AB_" to "YZ_"
how can i do it?
i have used grep and sed like,
grep -nr "AB_" ./ | xargs -0 sed -i 's/AB_/YZ_/g'
but giving error,
: File name too long
example string in a file are: Hello AB_WORLD! and Hello WORLD_AB!
Thanks.
sed will take multiple files as arguments, so this should work:
sed -i '/AB_/s//YZ_/g' *
(Note that -i is non-standard)
You mean grep -lr not grep -nr
-l gives you the file name; -n gives you the matching line with line number prepended
I like Perl for this one:
The -i option will save the original file with a.bak extension.
$ perl -i.bak -pe 's/^AB_/YZ_/' *.txt
grep -lr "AB_" ./ | while read file
do
echo "Change file $file ..."
sed -i 's/AB_/YZ_/g' ${file}
done
sed one-liner answer
Find php files in the directory containing string "foo" and replace all occurences with "bar"
grep -l foo *.php | xargs sed -i '' s/foo/bar/g
To recurse through directories
grep -rl foo * | xargs sed -i '' s/foo/bar/g
(just done successfully on 8100 files)
grep -rl bar * | wc -l
8102

I want to use "awk" or sed to print all the lines that start with "comm=" in a file

I want to use "awk" or "sed" to print all the lines that start with comm= from the file filex, Note that each line contains "comm=somthing"
for example : comm=rm , comm=ll, comm=ls ....
How can i achieve that ?
For lines that start with comm=
sed -n '/^comm=/p' filex
awk '/^comm=/' filex
If comm= is anywhere in the line then
sed -n '/comm=/p' filex
awk '/comm=/' filex
You could use grep also :
grep comm= filex
this will display all the lines containing comm=.
Here's an approach using grep:
grep -o '\<comm=[[:alnum:]]*\>'
This treats a word as consisting of alphanumeric characters; extend the character class as needed.
If grep is ok to use, you could give a try to:
grep -E "^comm=" file

Resources