I have a Rails application running on a CentOS 7 machine. I would like to read the system-configured region (Olson time zone) into a string (e.g. 'Europe/Stockholm', 'US/Eastern', etc).
I'm not interested in results that differ depending on whether daylight saving is active - 'CET' and 'CEST' and stuff like that won't do it for me. I've dug around Time and TZInfo but can't seem to find anything fitting.
Any ideas?
EDIT: It turns out Rails has no native way of getting the Olson time zone - one would have to do it in the shell, something like this. Neikos' suggestion below is shorter but doesn't work for me because my machine is a modified version of CentOS 7 which is stripped of timedatectl but is perhaps useful for someone else.
EDIT 2: I ended up calling the following shell script from within ruby:
#!/bin/bash
checksum=`md5sum /etc/localtime | cut -d ' ' -f1`
find /usr/share/zoneinfo/ -type f | xargs md5sum 2> /dev/null |
grep "^$checksum" | sed "s,.*/usr/share/zoneinfo/,," |
sort -n | head -n1
Since you are on CentOS 7 you could use something akin to timedatectl | grep Time zone and parse the timezone out of that.
This is obviously not portable to non-systemd systems.
As a not so pretty oneliner:
`timedatectl | grep "Time zone"`.split(/:|\(/)[1].strip
Related
I'm trying to find lines with words not preceded by double colons (::).
Example
void myClass::doMything() // I don't want this line
myObj->doMyThing() // I want this line
My goal is to get the lines where some methods are used, but not where the methods are defined.
I try with this command :
grep --color=always -rwna "methodName" --include=*.cpp | grep -v "::methodName"
but it doesn't work : it keeps extracting also lines containing
::methodName
I've also tried by writing
grep --color=always -rwna "methodName" --include=*.cpp | grep -v "\:\:methodName"
egrep --color=always -rwna "methodName" --include=*.cpp | egrep -v "\:\:methodName"
but neither works.
What should I do ?
Although grep is probably most common used tool among all linux CLI tools and is used by every1 and everywhere... still doesnt mean its perfect. The thing you are trying to achieve is not achievable with basic grep's regex - you need python/perl regex here.
As a workaround (I assume you are trying to only find line where method is invoked) you can try:
grep -Eno "(::)?methodName" your_input_files | grep -v "::methodName"
-n to prints line number and I believe it will give convenience to you
-o to prints only matched part, but I use it here to split output - to have each match in separate line (if you have 5x methodName in line of code you will have 5 lines in grep's output)
(::)? to find distinguish if its declaration or invokation of methodName, we will need it when 2nd grep comes to play...
grep -v ...and here it comes, to get rid of what you dont want
I guess you want to use maaaaany times so you can even try to make a function into your .bashrc
find_invocations () {
# below example goes through current dir, but you can improve it :)
grep --color=yes -Eno "(::)?$1" * 2>/dev/null | grep -v "::$1"
}
in above function you might go risky and use $1.* instead of $1 but an unpleasant case is if you have both methodname and ::methodName in same line AFAIR my C++ lessons (ages ago - anno 2010) methodName::methodName is a constructor...
...sorry for bad english
I've finally managed to make it work.
I've tried linux_beginner's suggestion:
grep -Eno '(::)?myMethodName' path/to/one/of/the/files.cpp | grep -v '::myMethodName'
with a single file and this works. (I found I prefer not using the o option, because I also want to se how it's used).
In this search I need anyway to use multiple files. So I've also tried to include more files :
grep -Eno '(::)?myMethodName' --include=*.cpp | grep -v '::myMethodName'
but in this case it remains like stuck in the search (maybe it triggers some slow scripting ? perl or python ?).
I've checked RavinderSingh13's command. Taken in a single instance, it can capture the lines with double colon(and only them, correctly), both on single file or in multiple files :
grep -rna '::myMethodName' path/to/one/of/the/file.cpp
grep -rna '::myMethodName' --include=*.cpp
but there must not be the -w switch, so the following:
grep -rna '::myMethodName' path/to/one/of/the/file.cpp
grep -rna '::myMethodName' --include=*.cpp
don't get any result.
RavinderSingh13's suggestion put inside the pipelining doesn't manage to filter out the double colon lines (my original goal), either with single or multiple files :
grep -rwna 'myMethodName' path/to/one/of/the/files.cpp | grep -v '::[[:alpha:]]+'
-> extracts both myMethodName and ::myMethodName from the chosen file
grep -rwna 'myMethodName' --include=*.cpp | grep -v '::[[:alpha:]]+'
-> extracts both myMethodName and ::myMethodName from all the cpp files
Now, how I could solve:
usually, when I concatenate grep commands I also add to the first of them the switch --color=always, which preserves results coloring also across the piping of multiple commands.
But that... was the culprit !
i.e., doing
grep --color=always -rwna 'myMethodName' --include=*.cpp | grep -v '::myMethodName'
preserves the color in results, but sadly fails to exclude lines containing ::myMethodName, while
grep -rwna 'myMethodName' --include=*.cpp | grep -v '::myMethodName'
gives colorless but correct results (manages to filter out double column lines).
The distribution on which I've experimented these codes and behaviours is Ubuntu 20.04.1 LTS.
Grep version : grep (GNU grep) 3.4
Thanks everybody for the interest.
The asterisk or star tells the engine to attempt to match the preceding token zero or more times. The plus tells the engine to attempt to match the preceding token once or more.
Based on the definition, I was wondering why the plus sign returns more matches than the asterisk sign.
echo "ABC ddd kkk DDD" | grep -Eo "[A-Z]+"
returns
ABC DDD
echo "ABC ddd kkk DDD" | grep -Eo "[A-Z]*"
returns
ABC
As far as I can tell, it doesn't. With GNU grep versions 2.5.3, 2.6.3, 2.10, and 2.12, I get:
$ echo "ABC ddd kkk DDD" | grep -Eo "[A-Z]+"
ABC
DDD
$ echo "ABC ddd kkk DDD" | grep -Eo "[A-Z]*"
ABC
DDD
Please double-check your second example. If you can confirm that you get only one line of output, it might be a bug in your grep. If you're using GNU grep, what's the output of grep --version? If not, what OS are you using, and (if you know) what grep implementation?
UPDATE :
I just built and installed GNU grep 2.5.1 (the version you're using) from source, and I confirm your output. It appears to be a bug in that version of grep, apparently corrected between 2.5.1a and 2.5.3. GNU grep 2.5.1 is about 12 years old; can you install a newer version? Looking through the ChangeLog for 2.5.3, I suspect this may have been the fix:
2005-08-24 Charles Levert <charles_levert#gna.org>
* src/grep.c (print_line_middle): In case of an empty match,
make minimal progress and continue instead of aborting process
of the remainder of the line, in case there's still an upcoming
non-empty match.
* tests/foad1.sh: Add two tests for this.
* doc/grep.texi, doc/grep.1: Document this behavior, since
--only-matching and --color are GNU extensions which are
otherwise unspecified by POSIX or other standards.
Even if you don't have full access on the machine you're using, you should still be able to download the source tarball from ftp://ftp.gnu.org/gnu/grep/ and install it under your home directory (assuming your system has a working compiler and associated tools).
So, something so simple, how much ram is installed in the current machine? I run a pxe image built in buildroot to grab system specifications from systems on a network boot. But, one thing seems to stick out to me. How do you effectively and reliably count the ram on every possible system.
I give you the worst code ever made, it's 6 years old and I am absolutely embarrassed by it.
ramtotal=0
ramsize=1
while test $ramsize -le 10000; do
ramcount=`dmidecode --type memory | grep -v Enabled | grep -v Installed | grep -v Maximum | grep "Size:" | grep "MB" | grep -c " $ramsize "`
ramup=$(( ramsize * ramcount ))
ramtotal=$(( ramtotal + ramup ))
ramsize=$(( ramsize * 2 ))
done
Well, may my code live long enough to be capable of counting ram chips with a size of 2^10000. Future proof ftw. And that's the thing, the code literally just worked, and so there was never any reason to make it disappear.
Today, I am trying a new code which worked fine on my Ubuntu Server, but not with busybox.
ramtotal=`dmidecode --type memory | grep -v Enabled | grep -v Installed | grep -v Maximum | grep "Size:" | grep "MB" | grep -o -P '(?<=\:\ ).*(?=\ MB)' | awk '{s+=$1} END {print s}'`
ramtotal=`dmidecode -t memory | grep "Size:" | awk '/Size: ([0-9]+) bytes|([kKMGTPEZ]B)/ {if($3 ~ /GB/) { size+=$2*1024 } else if($3 ~ /MB/) { size+=$2 } } END { print size }'`
So, it's been a long time since I originally posted. And I guess just to be consistent, I wanted to come back and update this, seeing as a change in the source code of dmidecode essentially breaks what I had previously added. Essentially for some reason dmidecode decided that this field could be MB or GB. (and perhaps something even bigger, though I didn't bother to research how forward thinking they decided to be).
I have some large text file(3 GB rails log file) on a centos os with a corrupted byte in this text file. When trying to search some pattern using grep, it runs indefinitely and I have to close it, however with pcregrep it takes less than a minute, so any clue why this difference ?
My search using grep:
grep -Pzo "2016-04-20(.*?)SomeController#index" production.log | wc -l
using pcregrep:
pcregrep -M "2016-04-20(.*?)SomeController#index" production.log | wc -l
I'm getting frustrated enough that I figured it was time to ask a question.
I'm trying to replace an email address across a website that is hard coded into 1000's of pages. It's on a FreeBSD 6.3 server.
Here is the command I am using:
grep -R --files-with-matches 'Email\#domain.com' . | sort | uniq | xargs perl -pi -e 's/Email\#domain.com/Email\#newdomain.com/' *.html
And here is the error that I keep getting:
xargs: unterminated quote
Oddly enough, when I run that command on a test case of 3 files (in a nested structure) it works just fine. I've been googling and most solutions seem to deal with adding a -print0 after the . and a -0 after the xargs. However, this yields a different set of errors that lead me to believe I'm putting things in the wrong places.
thanks in advance for your help
Pax is correct. I would further correct it to something like:
grep -R --files-with-matches 'Email\#domain.com' . -print0 | xargs -0 perl -pi -e 's/Email\#domain.com/Email\#newdomain.com/'
EDIT:
Thanks to kcwu, this is the full FreeBSD:
grep -R --files-with-matches 'Email\#domain.com' . --null | xargs -0 perl -pi -e 's/Email\#domain.com/Email\#newdomain.com/'
Note that I've removed sort and uniq. --files-without-match is documented to "stop on the first match" so you will not get duplicate files. -print0 and -0 ensure (and handle) a null-terminated file list, which is vital, because POSIX allows filenames to contain newlines.
Note that I don't know perl, but I'm assuming that part's roughly equivalent to:
sed -i s/Email\#domain.com/Email\#newdomain.com/g
Why are you giving a list of HTML files to xargs? That program takes its file list from the pipeline (output of grep).
Use GNU Parallel:
grep -R --files-with-matches 'Email\#domain.com' . | sort | uniq | parallel -q perl -pi -e 's/Email\#domain.com/Email\#newdomain.com/g'
Watch the intro video to learn more: http://www.youtube.com/watch?v=OpaiGYxkSuQ