44

The reason lies in the way RegEx matches are processed (see here, e.g.): The string is evaluated from left to right, and - except for backreferences - every single symbol in the string must be matched by a token in the regular expression (which in the simplest case is the literal symbol itself), although the token can be implicit thanks to repetition ...


31

The reason it isn't matching is because you are looking for whitespace (\s) before the string tty and at the end of your match. That never happens here since ls will print one entry per line. Note that ls is not the same as ls | command. When the output of ls is piped, that activates the -1 option causing ls to only print one entry per line. It will work as ...


20

The file is called .lename now. (This is assuming the file was called filename before, your "real" file will have a different name I guess. But however the file was called, the first two characters have been substituted with a ..) This is because a dot in regular expression is a special character meaning match any character. So, .. is any two characters. ...


18

sed ':a;/[|].*[|]/s/[|]/ /;ta' file /[|].*[|]/: If line has two pipes, s/[|]/ /: Substitute the first with a space. ta: If a substitution was made, go back to :a. Output: $ sed ':a;/[|].*[|]/s/[|]/ /;ta' file FLD1 SFK TK FLD2 FLD4 FLD5 - 20200515 NNNN |406 RCO 301 FLD1 SFK TK FLD2 FLD4 FLD5 - 20200515 NNNN |0 ...


17

Since your tag indicates "Regular expression", I assume you are referring to the POSIX character classes [:blank:] and [:space:]. This overview table shows that [:blank:] is a subset of [:space:]: [:space:] contains everything usually designated as "whitespace characters", i.e. "space" (the character \x20, generated when pressing the "space" bar), ...


17

Use the t command after each s command to branch to the end of the script if a substitution was made: sed -e 's/something/else/;t' \ -e 's/one/two/;t' \ -e 's/two/three/;t' <<<"one" Here, the t command after the last substitution is not needed, but if you generate this code automatically, there is no problem letting it suffix each s, even ...


17

Here's one way with [^a] (match any character other than a) instead of . (match any character): $ grep -E '^([^a]*a){3}[^a]*$' /usr/share/dict/cracklib-small | shuf -n 4 areaway humanitarian capitalizations autonavigator You can also write the regexp like ^[^a]*(a[^a]*){3}$ with the same results. It's also equivalent to ^[^a]*a[^a]*a[^a]*a[^a]*$ which ...


16

It would be more direct, in my opinion, to use a tool like awk that can: split fields for you test exactly the fields you want for the values you want For example: awk -F: '$4 == 1001 || $4 == 1003' mypasswd ... tells awk to: split the incoming lines into fields based on colons, with -F: uses an "or" expression to test whether field 4 has the value 1001 ...


16

There is no such thing as "blank", in this context. All you have are characters, and some characters that don't actually print anything visible to you in normal text. However, everything is expressed in terms of characters, yes. There are quite a few non-printing characters in ASCII, you can find a full list here: https://web.itu.edu.tr/sgunduz/courses/...


15

To include a hyphen in a character class it must be at the first or last position From find manual "the type of regular expression used by find and locate is almost identical to that used in GNU Emacs" and from Emacs manual: [ ... ] To include a ‘-’, write ‘-’ as the first or last character of the set, or put it after a range. Thus, ‘[]-]’ ...


15

That restriction is precisely documented. From: http://man.openbsd.org/awk.1#STANDARDS STANDARDS The awk utility is compliant with the IEEE Std 1003.1-2008 (“POSIX.1”) specification, except awk does not support {n,m} pattern matching.


15

Far simpler just to check the release string directly if grep -q 'release 7\.[56] ' /etc/redhat-release then ... The grep command matches by regular expression. The [56] atom matches 5 or 6, allowing the pattern to match on 7.5 or 7.6. Since . matches any character I've escaped it with a backslash so that it matches a literal dot. The trailing space ...


14

I have seen the below pattern is used in several places (even on sof) ... Why is it so popular? Because people are copy-pasting the first google search result in their answers, blogs and code, which are in turn picked up by search engines, which brings even more people to copy-paste it, generating an infernal vortex which finishes by driving off the ...


13

Why? because your shell interprets some special characters, such as \ in your example. You are running into troubles because you do not protect the string that you try to pass as argument to grep via the Shell. Several solutions: singlequoting the string, doublequoting the string (with doublequoting the shell will interpret several things, such as $...


13

Use the same sort of pattern to detect "at least 4 as", and invert the sense of the match: grep 'a.*a.*a' /usr/share/dict/words | grep -v 'a.*a.*a.*a' or, grep '\(a.*\)\{3\}' /usr/share/dict/words | grep -v '\(a.*\)\{4\}' or, grep -E '(a.*){3}' /usr/share/dict/words | grep -v -E '(a.*){4}' Alternatively, use awk with a as the field delimiter and count ...


12

It should not be used in production. For example "email me"@contoso.com is a syntactically valid email address but will not be matched by that naïve RE. See RFC5322 section 3.4.1 for the definitive grammar. Annoyingly perhaps, there is no BRE or ERE that can match that grammar definition, but you can get very close. However, a PCRE will do the ...


11

You can do this with bash's built-in string matching. Note that this uses glob (wildcard) patterns, not regular expressions. if [[ $(cat /etc/redhat-release | awk '{print $7}') == 7.[56] ]] Or, of we eliminate the UUoC: if [[ $(awk '{print $7}' /etc/redhat-release) == 7.[56] ]] or... if [[ $(cat /etc/redhat-release) == *" release 7."[56]" "* ]] or ...


11

A different approach from Quasímodo's explicit loop in sed: $ sed 'h; s/.*|//; x; s/|[^|]*$//; y/|/ /; G; y/\n/|/' file FLD1 SFK TK FLD2 FLD4 FLD5 - 20200515 NNNN |406 RCO 301 FLD1 SFK TK FLD2 FLD4 FLD5 - 20200515 NNNN |0 FLD1 SFK TK FLD2 FLD4 FLD5 - 20200515 NNNN |0 For each line, this ...


10

Use the \U function in GNU sed. s/^\([a-z]\)/\U\1/ so this captures a single character at the start of the line if it is lowercase, and upper cases it. As the \U leaves other things alone, this can be simplified to s/\(.\)/\U\1/ as the . will match the first character (if any) on the line.


9

The description in the linked article is wrong. The actual POSIX definition states that: The interpretation of an ordinary character preceded by an unescaped <backslash> ( '\' ) is undefined, except for [(){}, digits and inside a bracket expression] And ordinary characters are defined as any except the BRE special characters .[^$* and the ...


9

Turning the comments into an answer: The problem is that \ is the escape character both for regexes and the shell. \. is to the shell the same as '.'. echo and set -x help understand, what the shell does: > echo \. . > echo '\.' \. > echo \\. \. > set -x > echo 9_00 | grep 9\.00 + echo 9_00 + grep 9.00 9_00 So if the command shall see ...


9

Using Perl you could run something along the lines of perl -pe 's/\|(?=.*\|)/ /g' ex where: perl -pe action -- executes action and print \|(?=.*\|) is a regular expression that matches | with a not consumed lookeahed (?=.*|) containing another |


9

grep log.retention.bytes server.log{,.1} In order to keep log entries (appended) in chronological order, you might want to reverse the order of files: grep log.retention.bytes server.log{.1,} which is of course equivalent to: grep log.retention.bytes server.log.1 server.log as the brace expansion is done by the shell before executing the grep command. ...


8

Since all you're doing is adding two dashes, and dropping some extra characters, there's not much need for date. $ sed -Ee 's/(Last Password Change: )(....)(..)(..).*Z/\1\2-\3-\4/' < foo.txt ... Name: cust foo mail: cust.foo@example.com Account Lock: FALSE Last Password Change: 2017-07-21 ... For a stricter pattern, the dots (that match any ...


8

\s is the GNU regular expression shortcut way to write the POSIX expression [[:blank:]], which matches a space or a tab character (\s also matches newlines if these have been inserted into the pattern space of sed by means of other editing commands). The \s notation originally comes from Perl regular expressions, but in a Perl regular expression it works ...


8

In Zsh, you could do just rm stdout.<1-250>. <n-m> matches parts of the filename that represent a decimal integer number from n to m. (Possibly with leading zeroes, so stdout.0099 would also match.) In Bash, you could use brace expansion: rm stdout.{1..250}. Though the difference with Zsh's <1-250> is that brace expansion generates strings ...


8

you need: grep -P '\S\s{1,3}\S' infile \s matches a whitespace-character, not only a space. \S matches a non-whitespace-character in your attempt, you are not limiting that before &after your matches should not be a whitespace. to filter on space only and avoid using PCRE, you can do: grep '[^ ] \{1,3\}[^ ]' infile or to work on lines having leading/...


8

If you want to match on a sequence of 1 to 3 whitespace characters not surrounded by whitespaces, that's where you'd use Perl look-around operators: grep -P '(?<!\s)\s{1,3}(?!\s)' It matches on: 1 1234567890123456789 a b c d e ^ ^^ ^^^ With standard grep, you could achieve the same effect with: grep -E '(^|[^[:space:]])[[:space:]...


8

The complement of \s is \S, not [^\s] which (with the help of -i) excluded 'SIX' and 'Sam' from the result because they contain a literal s. How to grep -i for lines starting with "host", followed by one or more whitespaces and a sequence of one or more characters until the end of the line, where no literal * or whitespace can exist: grep -Ei '^...


7

[c1-c2] is a bracket expression. In the form given, it matches the character ”c”, the range of characters between “1” and “c” inclusive, and the character ”2”. The range of characters depends on the locale; in the POSIX locale, it’s the set of characters whose ASCII code is between 49 (the code for “1”) and 99 (the code for “c”). Thus: $ echo : | LANG=C ...


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