Execution of ls command in Linux - linux

I don't understand the execution when ?? and * are used together.
The following files are in the current working directory:
abc.txt
abcd.txt
bcd.txt
amm.doc
ammc.txt
What is the return result after executing command ls a??.*

* Matches any string, including the null string (empty string)
? Matches any single character
For exemples
Pattern a??.* matches abc.txt
- (a,a)
- (?,b)
- (?,c)
- (.,.)
- (*,txt)
Pattern a??.* don't matches abcd.txt
- (a,a)
- (?,b)
- (?,c)
- but . dont' matches with d
Pattern a??.* don't matches bcd.txt because a don't matches with b.

The questions marks will translate to any one character but the * will translate to multiple characters. Your example will only produce abc.txt and amm.doc. Look up Shell Globbing if you want to know more.

Related

How to grep the string with specific pattern

I am trying to grep a file.txt to search 2 strings cp and (target file name) where the line in file is as below,
cp (source file name) (target file name)
the problem for me here is string '(target file name)' has specific pattern as /path/to/file/TC_12_IT_(6 digits)_(6 digits)_TC_12_TEST _(2 digits).tc12.tc12
I am using below grep command to search a line with these 2 strings,
grep -E cp.*/path/to/file/TC_12_IT_ file.txt
how can I be more specific about (target file name) in grep command to search (target file name) with all its patterns, something like below,
grep -E 'cp.*/path/to/file/TC_12_IT_*_*_TC_12_TEST_*.tc12.tc12' file.txt
can we use wildcards in grep to search string in file just like we can use wilecard like * in listing out files e.g.
ls -lrt TC_12_*_12345678.txt
please suggest if there are any other ways to achieve this.
More specifically:
grep -P '^cp\s+.+\s+\S+/TC_12_IT_\d{6}_\d{6}_TC_12_TEST _\d2[.]tc12[.]tc12$' in_file > out_file
^ : beginning of the line.
\s+ : 1 or more whitespace characters.
.+ : 1 or more any characters.
\S+ : 1 or more non-whitespace characters.
\d{6} : exactly 6 digits.
[.] : literal dot (.). Note that just plain . inside a regular expression means any character, unless it is inside a character class ([.]) or escaped (\.).
$ : end of the line.
SEE ALSO:
GNU grep manual
perlre - Perl regular expressions
Like this, using GNU grep:
grep -P 'cp.*TC_12_IT_\d{6}_\d{6}TC_12_TEST\d{2}.tc12.tc12' file
The regular expression matches as follows:
Node
Explanation
cp
'cp'
.*
any character except \n (0 or more times (matching the most amount possible))
TC_12_IT_
'TC_12_IT_'
\d{6}
digits (0-9) (6 times)
_
_
\d{6}
digits (0-9) (6 times)
TC_12_TEST
'TC_12_TEST'
\d{2}
digits (0-9) (2 times)
.
any character except \n
tc12
'tc12'
.
any character except \n
tc12
'tc12'

Return substring before dash followed by a digit in bash

I have a string that can be one of:
1.) AA_BB-CC_xxxx-xx.y.y-xxxxxxxx-yyyyyy.tar.gz
or with prefix dropped:
2.) CC_xxxx-xx.y.y-xxxxxxxx-yyyyyy.tar.gz
where A,B,C,D are any number of letters and x and y are digits. I need to extract the following from the above:
AA_BB-CC_xxxx
CC_xxxx
Example:
standalone_version-WIN_2012-16.3.2-20180627-131137.tar.gz
WIN_2008-16.3.2-20180614-094525.tar.gz
need to extract:
standalone_version-WIN_2012
WIN-2008
I'm trying to discard everything from the end till the first dash followed by a digit is encountered. I'm using the following but it returns the whole string:
name=${image_file%%-[0-9].*}
You were almost there! Instead of
name=${image_file%%-[0-9].*}
omit the dot:
name=${image_file%%-[0-9]*}
The expressions in bash %% string trims are patterns, not regular expressions. Therefore * alone matches any number of characters, not .* as in a regex.
Example (tested in bash 4.4.12(3)-release):
$ foo='standalone_version-WIN_2012-16.3.2-20180627-131137.tar.gz'
$ bar='WIN_2008-16.3.2-20180614-094525.tar.gz'
$ echo ${foo%%-[0-9].*}
standalone_version-WIN_2012-16.3.2-20180627-131137.tar.gz
# oops
$ echo ${foo%%-[0-9]*}
standalone_version-WIN_2012
# no dot - works fine
$ echo ${bar%%-[0-9]*}
WIN_2008
# same here.

Bash: extract a part of a string, after a number

I have a few strings like this:
var1="string one=3423423 and something which i don't care"
var2="another bigger string=413145 and something which i don't care"
var3="the longest string ever=23442 and something which i don't care"
These strings are the output of a python script (which i am not allowed to touch), and I need a way to extract the 1st part of the string, right after the number. Basically, my outputs should be:
"string one=3423423"
"another bigger string=413145"
"the longest string ever=23442"
As you can see, i can't use positions, or stuff like that, because the number and the string length are not always the same. I assume i would need to use a regex or something, but i don't really understand regexes. Can you please help with a command or something which can do this?
grep -oP '^.*?=\d+' inputfile
string one=3423423
another bigger string=413145
the longest string ever=23442
Here -o flag will enable grep to print only matching part and -p will enable perl regex in grep. Here \d+ means one or more digit. So, ^.*?=\d+ means print from start of the line till you find last digit (first match).
You could use parameter expansion, for example:
var1="string one=3423423 and something which i don't care"
name=${var1%%=*}
value=${var1#*=}
value=${value%%[^0-9]*}
echo "$name=$value"
# prints: string one=3423423
Explanation of ${var1%%=*}:
%% - remove the longest matching suffix
= - match =
* - match everything
Explanation of ${var1#*=}:
# - remove the shortest matching prefix
* - match everything
= - match =
Explanation of ${value%%[^0-9]*}:
%% - remove the longest matching suffix
[^0-9] - match any non-digit
* - match everything
To perform the same thing on more than one values easily,
you could wrap this logic into a function:
extract_and_print() {
local input=$1
local name=${input%%=*}
local value=${input#*=}
value=${value%%[^0-9]*}
echo "$name=$value"
}
extract_and_print "$var1"
extract_and_print "$var2"
extract_and_print "$var3"
$ shopt -s extglob
$ echo "${var1%%+([^0-9])}"
string one=3423423
$ echo "${var2%%+([^0-9])}"
another bigger string=413145
$ echo "${var3%%+([^0-9])}"
the longest string ever=23442
+([^0-9]) is an extended pattern that matches one or more non-digits.
${var%%+([^0-9])} with %%pattern will remove the longest match of that pattern from the end of the variable value.
Refs: patterns, parameter substitution

Replace C statement with substitute in vim

I would like to use vim's substitute function (:%s) to search and replace a certain pattern of code. For example if I have code similar to the following:
if(!foo)
I would like to replace it with:
if(foo == NULL)
However, foo is just an example. The variable name can be anything.
This is what I came up with for my vim command:
:%s/if(!.*)/if(.* == NULL)/gc
It searches the statements correctly, but it tries to replace it with ".*" instead of the variable that's there (i.e "foo"). Is there a way to do what I am asking with vim?
If not, is there any other editor/tools I can use to help me with modifications like these?
Thanks in advance!
You need to use capture grouping and backreferencing in order to achieve that:
Pattern String sub. flags
|---------| |------------| |-|
:%s/if(!\(.*\))/if(\1 == NULL)/gc
|---| |--|
| ^
|________|
The matched string in pattern will be exactly repeated in string substitution
:help /\(
\(\) A pattern enclosed by escaped parentheses. /\(/\(\) /\)
E.g., "\(^a\)" matches 'a' at the start of a line.
E51 E54 E55 E872 E873
\1 Matches the same string that was matched by /\1 E65
the first sub-expression in \( and \). {not in Vi}
Example: "\([a-z]\).\1" matches "ata", "ehe", "tot", etc.
\2 Like "\1", but uses second sub-expression, /\2
... /\3
\9 Like "\1", but uses ninth sub-expression. /\9
Note: The numbering of groups is done based on which "\(" comes first
in the pattern (going left to right), NOT based on what is matched
first.
You can use
:%s/if(!\(.*\))/if(\1 == NULL)/gc
By putting .* in \( \) you make numbered captured group, which means that the regex will capture what is in .*
When the replace starts then by using \1 you will print the captured group.
A macro is easy in this case, just do the following:
qa .............. starts macro 'a'
f! .............. jumps to next '!'
x ............... erase that
e ............... jump to the end of word
a ............... starts append mode (insert)
== NULL ........ literal == NULL
<ESC> ........... stop insert mode
q ............... stops macro 'a'
:%norm #a ........ apply marco 'a' in the whole file
:g/^if(!/ norm #a apply macro 'a' in the lines starting with if...
Try the following:
%s/if(!\(.\{-}\))/if(\1 == NULL)/gc
The quantifier .\{-} matches a non-empty word, as few as possible (more strict than .*).
The paranthesis \( and \) are used to divide the searched expression into subexpressions, so that you can use those subgroups in the substitute string.
Finally, \1 allows the user to use the first matched subexpression, in our case it is whatever is caught inside the paranthesis.
I hope this is more clear, more information can be found here. And thanks for the comment that suggests improving the answer.

Powershell Search String in File Containing $

I want to search the following string in a text file: $$u$$
I tried select-string, get-content, .Contains. It seems to me it's not possible.
I used this for the search as a variable: $ToSearch = "'$'$u'$'$"
It always gives false result.
It is because most search filters are relying on regex. The $ symbol in regex needs to be escaped
Without knowing more of what you're trying to accomplish I can't give much of an example, but here is one:
'this is a $$u$$ test' -replace "\$",""
The '\' is what is escaping the character - meaning to translate it literally.
Edit: Per comment
$Val = 'this is a $$u$$ test'
$Val | Select-String "\$+\w\$+" -quiet
-Quiet switch returns t/f rather than a string value.
The $ is a reserved character in regex, which is complicating your search.
The default search pattern type for Select-String is regex, but you can also specify -Simplematch or -Wildcard, either of which will eliminate the need to escape the $. If you use -Wildcard, you'll need to include the wilcard * at either end of the match - '*$$u$$*'. For simplematch, just use the string you want to match for - '$$u$$'.

Resources