Hot answers tagged

29

There are two problems with your example. The primary one is that you're assuming that regular expressions work the same as glob patterns in that * is a wildcard meaning "any sequence of characters." In regular expressions, * means "any number of the previous atom" instead, so fil* means f followed by i followed by zero or more l characters. You need to say ...


7

Use awk to match the line and split it into words separated by ( or ). Take the 2nd word $2, or preferably the next-to-last $(NF-1) if you might have parentheses in the device name: awk -F '[()]' '/Mouse/{print $(NF-1)}'


6

\< and \> match empty string at the begin and end of a word respectively and only word constituent characters are: [[:alnum:]_] From man grep: Word-constituent characters are letters, digits, and the underscore. So, your Regex is failing because / is not a valid word constituent character. Instead as you have spaces around, you can use -w option ...


5

ShellCheck is a good start for bash programming. It gives quite useful hints: Line 6: if [[ "$CDTRACK" =~ "([[:alpha:][:blank:]]*)- ([[:digit:]]*) - (.*)$" ]] ^-- SC2076: Don't quote rhs of =~, it'll match literally rather than as a regex. Regex can't be quoted like this. Working example with escaped special characters (basically ...


5

sed does not understand \d. You can use [0-9] or, more generally, [[:digit:]] in its place: $ sed -r 's/.*(X[[:digit:]])(.*)45.*/\1\2/' test.txt X1yad X2fad X3had X4wad X5mad Note that [[:digit:]] is unicode-safe but [0-9] is not.


5

Using extended globs: shopt -s extglob printf '%s\n' !([[:digit:][:upper:]]?([[:digit:][:upper:]])_[[:digit:]][[:digit:]][[:digit:]][[:digit:]]_+([[:alnum:]]).dat) this will print all file/directory names that do not (!) match [[:digit:][:upper:]] followed by zero or one [[:digit:][:upper:]] followed by 4 [[:digit:]] in between _s and then one or more ...


4

The fact that you can do something in bash doesn't mean that you should. sh (and bash etc) scripts are best suited to be relatively simple wrappers to launch programs or around text-processing commands. For more complicated tasks, including parsing ini files and acting on them, other languages are more appropriate. Have you considered writing your script ...


3

There are many ways of doing this. You could use a scripting language that understands regular expressions. For example, in Perl: perl -le 'unlink(grep(!/[0-9A-Z]{1,2}_\d{4}_\w+?.dat/,@ARGV))' * That will look for all files (not subdirectories) in the current directory, collect those that don't match the regex and delete them. You could also do a ...


2

You can use either of these, depending on what you're trying to display: $ echo "lol llol" | grep -E "\blol" lol llol $ echo "lol llol" | grep -Eo "\blol" lol Putting the regex in quotes solves your matching problem. The -o flag causes grep to only print the matched string instead of the entire line.


2

As is often the case on Solaris, /usr/bin/egrep is a legacy implementation that isn't POSIX-compliant, while /usr/xpg4/bin/egrep is a POSIX-compliant implementation and has little if anything beyond POSIX. Unless you're running legacy Solaris applications from the pre-POSIX days, make sure that /usr/xpg4/bin is before /usr/bin in your $PATH. GNU tools ...


2

If you want something more general than matching a specific character, you would have to use regular expressions. Since the question is not tagged "linux", the proper answer would use POSIX: find . | grep '[*~]' If you want to make it Linux-specific, you can use the GNU find option -regex (also supported by FreeBSD). If the pathname has an embedded ...


2

Using grep with PCRE (-P): bt-device --list | grep -Po 'Mouse\s.*?\(\K[^)]+' Mouse\s.*?\( will match Mouse in the line and then upto first (, \K will discard the match [^)]+ will get us the desired portion i.e. characters upto the next ) Example: $ cat file.txt Added devices: Logitech K811 (00:1F:20:EB:06:E0) Plattan ADV Wireless (5C:EB:68:1F:D1:62) ...


2

Plain grep uses basic regular expressions. Your regex uses -d and ? and {m,n} that aren't recognized. You want grep -E, but that may not recognize \d. If not change it to [0-9] grep -Erle '[3-6][0-9]{3}([ -]?)[0-9]{4}([ -]?)[0-9]{4}([ -]?)[0-9]{3,4}' * Or use grep -P to use perl-compatible regexes Ref: ...


2

The first regex searches for any line containing the following: '^ - start of line, followed by [^,]* - 0 or more non-comma characters, followed by , - a comma, followed by [^0] - any single character other than a zero, followed by [^,]* - 0 or more non-comma characters, followed by ,' - a comma grep -c counts the number ...


2

With sed: LC_ALL=C sed -e 's/\([0-9]\{4\}\)\([0-9]\{2\}\)\([0-9]\{2\}\)/\1_\2_\3/' <file


2

--exclude-dir does not understand |. You can, however, get the same effect by specifying --exclude-dir multiple times, one for each directory that you want to exclude: grep -inRw -E --exclude-dir 'asset' --exclude-dir 'git' --exclude-dir 'log' 'direct'


1

There are variances and limitations in how regexs get evaluated based on the utility being provided the expression, the arguments used when calling the command, the shell the command is called in, among other issues. With that said, the last section of the regex is what is blocking the match when I use it with grep; it is not listed as optional so it is ...


1

Replacing with Grep You can do (most of) this with regular expression search/replace. Use the Replace dialog, making sure that "Use Regular Expressions" is selected and "Use multi-line matching" is not. Search for: \\stylea{(.*)} And replace with: \1 This is a regular expression "back reference" to the "captured" text in the search expression (the ...


1

You don't need to get the database name, there's no point in replacing something with itself. Just leave it unchanged: beg="mysqli_connect(" new="'localhost','root','pass'," sed "s/$beg\([^,]\+,\)\{3\}/$beg$new/" file If I save the example you gave as file, that returns: $ sed "s/$beg\([^,]\+,\)\{3\}/$beg$new/" file sadnkjnadsjknfaskdjfnlasdnfkdsa ...


1

The man page description for that option is sort of misleading... It's pattern as in globs not pattern as in regex. Per the info page: --exclude-dir=GLOB Skip any command-line directory with a name suffix that matches the pattern GLOB. When searching recursively, skip any subdirectory whose base name matches GLOB. Ignore any redundant trailing ...


1

Implementations of find vary, but they should all handle character classes in wildcards (POSIX.2, section 3.13): find . -name '*[~*]*' If newline is among your "special" characters, you may need to work out how to get your shell to pass it to find. In Bash, you can use find . -name $'*[\t \n]*' to show files containing whitespace, for example. A ...


1

-name takes wildcard patterns, not regexps and matches on the file name, not its full path. Use -regex (or -iregex) for regexp matching but beware it matches against the full path. Here, you could do: LC_ALL=C find -E . -iregex '.*s[0-9]{1,2}\.?e[0-9]{1,2}[^/]*\.mkv' Here, we're replacing the second .* with [^/]*, that is a sequence of non-/ characters to ...


1

Unfolding that one-liner and rearranging a bit, plus a few tweaks, gets: cat /dev/urandom | \ tr -dc 'a-zA-Z0-9' | \ fold -w 16 | \ tr -d '[A-z]' | \ grep '....' | \ head -n 16 Outputs: 7405935 60722 11225 96954 3966 8774 539418 1964 59150 5994 1086 7470 2751 8534 21501 14927 Note: the n-digit numbers are probably random if taken ...


1

sed 's/abcd\(X[0-9][a-z]ad\)45das/\1/g' your_file_name should do it.



Only top voted, non community-wiki answers of a minimum length are eligible