This question already has answers here:
bash wildcard n digits
(4 answers)
Closed 2 years ago.
How can I match a more complex pattern when using cat or zcat? For example, I know I can do this:
zcat /var/log/nginx/access.log.*.gz
Which will output all the gzipped access logs to stdin.
What if I want a more complex pattern? Say, all the log files that are between 1-15, e.g. something like this pattern:
zcat /var/log/nginx/access.log.([1-9]|1[0-5]).gz
This results in an unexpected token which is obvious, but I'm not sure how I'd escape the regex in this situation? Maybe I need to pipe ls output to zcat instead?
It depends of course on specifically what pattern you want to match. For the example you have given of log files 1-15, you could use something like
cat /var/log/nginx/access.log.{1..15}.gz
which will complain to stderr if any of those numbers don't exist, but it will still concatenate the rest to stdout.
This technique is a "sequence expression" if you want to look it up - it's a part of brace expansion.
Related
This question already has answers here:
What is the meaning of the ${0##...} syntax with variable, braces and hash character in bash?
(4 answers)
What does "##" in a shell script mean? [duplicate]
(1 answer)
Closed 7 months ago.
I came across a shell script like the following:
for FILE_PATH in `ls some/directory`
do
export FILE=${FILE_PATH##*/}
done
What exactly is the "##*/" doing? When I echo ${FILE} and ${FILE_PATH}, I don't see any difference. Is this to handle unusually named files?
More generally, how would I go about figuring out this type of question for myself in the future? Google was completely useless.
It's removing everything up to the last / in the value of $FILE. From the Bash Manual:
${parameter#word}
${parameter##word}
The word is expanded to produce a pattern and matched according to the rules described below (see Pattern Matching). If the pattern matches the beginning of the expanded value of parameter, then the result of the expansion is the value of parameter with the shortest matching pattern (the ‘#’ case) or the longest matching pattern (the ‘##’ case) deleted.
You're not seeing any difference in this case because when you list a directory it just outputs the filenames, it doesn't include the directory portion, so there's nothing to remove. You would see the difference if you did:
for FILE in some/directory/*
This question already has answers here:
How can I replace a pattern only on lines that do or do not contain another pattern?
(2 answers)
Closed 1 year ago.
Is there a way to specifically search for a pattern first and then replace using %s
Why I specifically chose vim is because I can easily make change using :wq
Consider I got a file abc.txt where I need to replace all two's with three:
cat abc.txt
one two
two two
one two
But I only need to replace only those lines that is having "one".
Is there a way to first grep or filter lines having "one" inside vim and then replace using
:%s/two/three/g.
I need a one-liner command that can filter out all lines having "one" and perform substitution.
Sample output
cat abc.txt
one three
two two
one three
Many thanks in advance!
Use a Capture Group or a Look Behind Pattern to Solve Substitution
This ex command should meet your needs:
:`%s/\(one\) two/\1 three/
This is also a classic look behind pattern matching problem (:help /#<=).
:%s/\(one\)\#<= two/ three/
Another approach might be to use \zs, \ze pattern matching technique. Look up :help \zs.
%s/one \zstwo\ze/three/
This question already has answers here:
What's the magic of "-" (a dash) in command-line parameters?
(5 answers)
Closed 5 years ago.
I saw this line of code the other day and I didn't know exactly what is this - or when to use it. This is a simple code and from what I understood is that - takes the piped output and treats it as an argument of paste (correct me if I'am wrong)
seq $size | paste - $file
My question is when can we use this and is there another way to do the same thing?
Thanks,
This is documented in the man page for paste which says:
With no FILE, or when FILE is -, read standard input.
That is, paste expects you to give it a filename, but you can instead give it a single - instead, which paste will interpret as it should read data from stdin , your pipe in this case, instead of opening a file and read data from that file.
This question already has answers here:
How to preserve line breaks when storing command output to a variable?
(2 answers)
Closed 7 years ago.
If I grep our syslogs for a specific term, I get a nice output of those logs matching my term and each entry on a separate line.
If I save that to a variable so I can use it in a script as such:
results=$( grep "term" logs )
echo $results
then all the logs run together and are not human readable.
How can I make it look cleaner so when I do echo $results, I can actually read the output?
Thanks,
Quote it:
echo "$results"
This preserves all the whitespace, instead of using it for word splitting.
In general, you should almost always quote variables, unless you have a specific reason not to.
This question already has answers here:
Using different delimiters in sed commands and range addresses
(3 answers)
Closed 1 year ago.
I saw a bash command sed 's%^.*/%%'
Usually the common syntax for sed is sed 's/pattern/str/g', but in this one it used s%^.* for the s part in the 's/pattern/str/g'.
My questions:
What does s%^.* mean?
What's meaning of %% in the second part of sed 's%^.*/%%'?
The % is an alternative delimiter so that you don't need to escape the forward slash contained in the matching portion.
So if you were to write the same expression with / as a delimiter, it would look like:
sed 's/^.*\///'
which is also kind of difficult to read.
Either way, the expression will look for a forward slash in a line; if there is a forward slash, remove everything up to and including that slash.
the usually used delimiter is / and the usage is sed 's/pattern/str/'.
At times you find that the delimiter is present in the pattern. In such a case you have a choice to either escape the delimiter found in the pattern or to use a different delimiter. In your case a different delimiter % has been used.
The later way is recommended as it keeps your command short and clean.