Faced with the problem of parsing version of clang for different vendors clang --version|head -1
Apple LLVM version 6.0 (clang-600.0.54) (based on LLVM 3.5svn) => 3.5
FreeBSD clang version 3.4.1 (tags/RELEASE_34/dot1-final 208032) 20140512 => 3.4.1
clang version 3.5.0 (tags/RELEASE_350/rc2) => 3.5.0
Now have this regular expression
match: (clang version|based on LLVM)\ (\d+)(\.\d+)(\.\d+)?
to \2\3\4
I need to exclude (clang version|based on LLVM) from the result match() - \1.
Your question looks like you're expecting CMake's regex handling to be Perl-like, but it's pretty different.
In CMake syntax, the following should do what you want:
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
execute_process(COMMAND clang --version COMMAND head -1 OUTPUT_VARIABLE ClangVersionLine)
string(REGEX MATCH "(clang version|based on LLVM) ([0-9]\\.[0-9]\\.?[0-9]?)" UnusedVar "${ClangVersionLine}")
set(ClangVersion "${CMAKE_MATCH_2}")
message("ClangVersion - ${ClangVersion}")
endif()
Ok, since the tool you use is based on PCRE, this pattern should work:
(?m)(?:^Apple .*)?\K \d+(?:\.\d+){1,2}
The (?m) is not useful in real life because you only test one line, so you can remove it.
The \K removes all that have been matched on the left from the match result.
If you use another language/tool where the \K feature is not available you can use a capturing group to extract the information you want from the whole match result:
(?:^Apple .*)? ([0-9]+(?:[.][0-9]+){1,2})
With cmake:
string(REGEX REPLACE "(^Apple .*)? ([0-9]+([.][0-9]+){1,2}).*" "\\2" CLANG_VERSION "${_clang_version_info}")
Related
On a CI machine I have cmake echoing back some basic compiler variables at the start. After updating clang from 12 to 13, I am seeing both versions here:
-- CMAKE_C_COMPILER: /usr/local/bin/clang
-- CMAKE_C_COMPILER_ID: Clang
-- CMAKE_C_COMPILER_VERSION: 12.0.0
clang version 13.0.0 (/tmp/llvm-project/clang d7b669b3a30345cfcdb2fde2af6f48aa4b94845d)
-- CMAKE_CXX_COMPILER: /usr/local/bin/clang++
-- CMAKE_CXX_COMPILER_ID: Clang
-- CMAKE_CXX_COMPILER_VERSION: 12.0.0
clang version 13.0.0 (/tmp/llvm-project/clang d7b669b3a30345cfcdb2fde2af6f48aa4b94845d)
Note that "13.0.0" comes from actually running clang --version via these cmake functions:
message(STATUS "CMAKE_C_COMPILER: " ${CMAKE_C_COMPILER} )
message(STATUS "CMAKE_C_COMPILER_ID: ${CMAKE_C_COMPILER_ID}")
message(STATUS "CMAKE_C_COMPILER_VERSION: ${CMAKE_C_COMPILER_VERSION}")
execute_process(COMMAND ${CMAKE_C_COMPILER} ${COMPILER_VERSION_ARG} )
Additional info that might be relevant:
-- CMake version: 3.18.1-g262b901
-- Using ccache.
-- Using sanitizer: address
The issue becomes relevant because some later build steps fail as they are checking the compiler version and thus making the wrong decisions. Is there some local caching that could result in such weird behavior? To my understanding this should not be dependent on caching though?
Update: I tossed the CMAKE_C_COMPILER_VERSION check and used check_c_compiler_flag instead, see my answer below.
CMake found /usr/local/bin/clang, not /tmp/llvm-project/clang. You might want to explicitly set CMAKE_C_COMPILER and CMAKE_CXX_COMPILER to ensure that CMake finds the Clang you intend it should be used.
Clang 13 introduced two new checks that broke some external libs. Instead of checking the clang version doing a feature check is better anyway:
# clang 13 introduced stricter checks, for now, disable the warning:
include(CheckCCompilerFlag)
check_c_compiler_flag(-Wno-unused-but-set-variable HAS_UNUSED_BUT_SET_VARIABLE)
if (HAS_UNUSED_BUT_SET_VARIABLE)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-but-set-variable")
endif()
The same can be applied to -Wno-unused-but-set-parameter, of course. Also use CheckCxxCompilerFlag/check_cxx_compiler_flag instead for C++.
I have a source on which I have no control and I want to filter out all string which have some characters in it.
For example Out of these:
9
8.1.0
5.0
9.0
5.1
8.0.0
7.0 (cdfsdsdsd)
5.0.2
8
7.0.1
7.1
6.0
7.0
Over 32323
7.0 rdx K9 bnsm
9.2.3
8.oo
pp
unknown
8.0_vgfe10051988
6.0.1
8.0.0-derv10051988
9.1
9.0.0
8.0.1
7.0_xccv10051988
7.1.3
10.0
7.0.X.1.C
8.0.0_vged10051988
4.4.4
7.1.2
7.0 [NKL 24 | ABC]
8.1
7.1.1
5.1.1
7.0_Jgrd10051988
9.XXX
9.0.1
8.0
5.0.1
8.1.1
10
Out of these I need only those Strings with only digits and .
9
8.1.0
5.0
9.0
5.1
8.0.0
5.0.2
8
7.0.1
7.1
6.0
7.0
9.2.3
6.0.1
9.1
9.0.0
8.0.1
7.1.3
10.0
4.4.4
7.1.2
8.1
7.1.1
5.1.1
9.0.1
8.0
5.0.1
8.1.1
10
I have tried many regex, but nothing seems to be generic enough,
This regex is giving [0-9]*.?[0-9] Strings too.
The one I have got working is ^(\*|\d+(\.\d+){0,2}(\.\*)?)$, but this is not POSIX.
How do I get a POSIX which also works on Redshift?
By taking a look of the Amazon document, it seems POSIX ERE is supported by the Redshift. Then would you please try:
^[[:digit:]]+(\.[[:digit:]]+)*$
Your regex works, you just need to use double backslashes in the string literal.
According to the Amazon Redshift "POSIX Operators" documentation,
Amazon Redshift supports the following Perl-influenced operators in regular expressions. Escape the operator using two backslashes (‘\\’).
So, you may use
'^(\\*|\\d+(\\.\\d+){0,2}(\\.\\*)?)$'
The simplest is:
^[.0-9]+$
If you don't have support for extended regex, you can do:
^[.0-9][.0-9]*$
I ran this command on your input and output and got an empty diff:
$ diff <(grep -P '^[.0-9]+$' input) output
$ echo $?
0
On your specific input, even ^[.0-9]*$ would work.
Note, however, that there's a difference between "Strings with only digits and ." and "version string". The simple regex will also catch inputs like:
1..2
..
.
0...
.1
If that's not a problem, you can use the simple regex.
I have a C++ project using QMake. I'm trying to set some compiler options based on a simple test of which Linux distro is running, but the test does not pass. My qmake file contains:
OSDISTRO = $$(cat /proc/version)
contains(OSDISTRO, "Ubuntu"): {
message(Found ubuntu)
}
I tested the regex from the command line and it works!
cat /proc/version | pcregrep "Ubuntu"
Linux version 4.18.0-20-generic (buildd#lcy01-amd64-020) (gcc version 7.3.0 (Ubuntu 7.3.0-16ubuntu3)) #21~18.04.1-Ubuntu SMP Wed May 8 08:43:37 UTC 2019
Is there something special about the regex syntax in qmake? Any reason why this isn't working?
For the RegEx:
This works for me:
OSDISTRO = $$system(cat /proc/version)
contains(OSDISTRO, .*Ubuntu.*){
message("Found Ubuntu")
}
Note:
The match is case sensitive.
You can use .*[uU]buntu.* for example to match ubuntu and Ubuntu.
Explanation why your solution does not work:
The QMake function contains works with lists of values.
So, the execution of you solution will be like this:
1) First instruction OSDISTRO = $$(cat /proc/version):
QMake will execute $$system(cat /proc/version).
Then the result is splitted (by space as separator) to list of values. OSDISTRO will contain this list.
Assuming that the result is as yours. The result of the first instruction is like this:
OSDISTRO = "Linux" "version" "4.18.0-20-generic"....
2) Second instruction contains(OSDISTRO, "Ubuntu") : message(Found ubuntu):
QMake will search if the variable OSDISTRO contains the value Ubuntu and display the message Found ubuntu if success.
Here in your case, QMake will never find Ubuntu, cause the value which contains it is like this (Ubuntu 7.3.0-16ubuntu3) and QMake search only the value Ubuntu.
Hope it helps you.
In
AXyz122311Xyslasd22344ssaa Aklsssx#sdddf#4=sadsss kaaAASds
How do we get the characters "slas" out that begins with "11Xy" and ends with "d223" in UNIX using regular expression?
This is what lookahead and lookbehind assertions will do.
Have you tried something like this?
(?<=11Xy).+(?=d223)
Update
You can use grep -o to display only the matched text in a *nix environment.
Not too late, but, downvoters need to include that *NIX grep has a few limitations and lookaround/lookbehind/etc., do not actually work on most versions.
http://www.regular-expressions.info/grep.html
Since neither grep nor egrep support any of the special features such as lazy repetition or lookaround,
Only, recently was it added to GNU grep (3.0 ?) released recently which basically uses perl compatible regex
https://www.gnu.org/software/grep/manual/grep.html#The-Backslash-Character-and-Special-Expressions
-P
--perl-regexp Interpret the pattern as a Perl-compatible regular expression (PCRE). This is highly experimental, particularly when combined with the -z (--null-data) option, and ‘grep -P’ may warn of unimplemented features.
On upgrading my grep and using -P, it works like a charm
$cat test.txt | ggrep -oP '(?<=11Xy)(.*?)(?=d223)'
slas
$ggrep --version
ggrep (GNU grep) 3.1
Packaged by Homebrew
Copyright (C) 2017 Free Software Foundation, Inc.
...
On some OS, especially mac, your grep is BSD, so you have install GNU grep using homebrew to use it.
$grep -V
grep (BSD grep) 2.5.1-FreeBSD
$brew install grep
...
$ggrep -V
I am trying to kernel & gcc version by reading /proc/version file using Perl. But I am not sure but the regex to match the versions. I tried something like this
/Linux version (\d+)*gcc version(\d+)*/
But its not working. Thanks in advance. I am newbie to Perl. And the contents of version is
Linux version 2.6.32-21-generic (buildd#rothera) (gcc version 4.4.3
(Ubuntu 4.4.3-4ubuntu5) ) #32-Ubuntu SMP Fri Apr 16 08:10:02 UTC 2010
Try this:
$version =~ /Linux version ([\d.-]+)-\D.*gcc version ([\d.]+) /;
print "Linux version: $1\ngcc version: $2\n";
The output:
Linux version: 2.6.32-21
gcc version: 4.4.3
This regex will work for you
/Linux version ([\w.-]*).*?gcc version ([\w.]*)/
First captured group will have linux version 2.6.32-21-generic and second captured group will have gcc version 4.4.3. If you do not want to capture generic then use \d instead of \w.
m{Linux version\s(\S+).*gcc version\s(\S+)} and print "$1\n$2\n"