mirror of
https://github.com/systemd/systemd-stable.git
synced 2024-10-27 01:55:32 +03:00
journalctl: make matching optionally case sensitive
Case sensitive or case insensitive matching can be requested using --case-sensitive[=yes|no]. Unless specified, matching is case sensitive if the pattern contains any uppercase letters, and case insensitive otherwise. This matches what forward-search does in emacs, and recently also --ignore-case in less. This works surprisingly well, because usually when one is wants to do case-sensitive matching, the pattern is usually camel-cased. In the less frequent case when case-sensitive matching is required with an all-lowercase pattern, --case-sensitive can be used to override the automatic logic.
This commit is contained in:
parent
6becf48ca3
commit
61c5f8a1f0
@ -586,7 +586,19 @@
|
||||
field matches the specified regular expression. PERL-compatible regular expressions
|
||||
are used, see
|
||||
<citerefentry><refentrytitle>pcre2pattern</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
||||
for a detailed description of the syntax.</para></listitem>
|
||||
for a detailed description of the syntax.</para>
|
||||
|
||||
<para>If the pattern is all lowercase, matching is case insensitive.
|
||||
Otherwise, matching is case sensitive. This can be overridden with the
|
||||
<option>--case-sensitive</option> option, see below.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--case-sensitive<optional>=BOOLEAN</optional></option></term>
|
||||
|
||||
<listitem><para>Make pattern matching case sensitive or case insenstive.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
|
@ -83,6 +83,7 @@
|
||||
|
||||
#if HAVE_PCRE2
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(pcre2_match_data*, pcre2_match_data_free);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(pcre2_code*, pcre2_code_free);
|
||||
|
||||
static int pattern_compile(const char *pattern, unsigned flags, pcre2_code **out) {
|
||||
int errorcode, r;
|
||||
@ -159,7 +160,9 @@ static usec_t arg_vacuum_time = 0;
|
||||
static char **arg_output_fields = NULL;
|
||||
|
||||
#if HAVE_PCRE2
|
||||
static pcre2_code *arg_pattern = NULL;
|
||||
static const char *arg_pattern = NULL;
|
||||
static pcre2_code *arg_compiled_pattern = NULL;
|
||||
static int arg_case_sensitive = -1; /* -1 means be smart */
|
||||
#endif
|
||||
|
||||
static enum {
|
||||
@ -332,6 +335,7 @@ static void help(void) {
|
||||
" -t --identifier=STRING Show entries with the specified syslog identifier\n"
|
||||
" -p --priority=RANGE Show entries with the specified priority\n"
|
||||
" -g --grep=PATTERN Show entries with MESSSAGE matching PATTERN\n"
|
||||
" --case-sensitive[=BOOL] Force case sensitive or insenstive matching\n"
|
||||
" -e --pager-end Immediately jump to the end in the pager\n"
|
||||
" -f --follow Follow the journal\n"
|
||||
" -n --lines[=INTEGER] Number of journal entries to show\n"
|
||||
@ -409,6 +413,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
ARG_DUMP_CATALOG,
|
||||
ARG_UPDATE_CATALOG,
|
||||
ARG_FORCE,
|
||||
ARG_CASE_SENSITIVE,
|
||||
ARG_UTC,
|
||||
ARG_SYNC,
|
||||
ARG_FLUSH,
|
||||
@ -449,6 +454,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
{ "identifier", required_argument, NULL, 't' },
|
||||
{ "priority", required_argument, NULL, 'p' },
|
||||
{ "grep", required_argument, NULL, 'g' },
|
||||
{ "case-sensitive", optional_argument, NULL, ARG_CASE_SENSITIVE },
|
||||
{ "setup-keys", no_argument, NULL, ARG_SETUP_KEYS },
|
||||
{ "interval", required_argument, NULL, ARG_INTERVAL },
|
||||
{ "verify", no_argument, NULL, ARG_VERIFY },
|
||||
@ -801,20 +807,23 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
#if HAVE_PCRE2
|
||||
case 'g': {
|
||||
if (arg_pattern) {
|
||||
pcre2_code_free(arg_pattern);
|
||||
arg_pattern = NULL;
|
||||
}
|
||||
r = pattern_compile(optarg, 0, &arg_pattern);
|
||||
case 'g':
|
||||
arg_pattern = optarg;
|
||||
break;
|
||||
|
||||
case ARG_CASE_SENSITIVE:
|
||||
if (optarg) {
|
||||
r = parse_boolean(optarg);
|
||||
if (r < 0)
|
||||
return r;
|
||||
return log_error_errno(r, "Bad --case-sensitive= argument \"%s\": %m", optarg);
|
||||
arg_case_sensitive = r;
|
||||
} else
|
||||
arg_case_sensitive = true;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
#else
|
||||
case 'g':
|
||||
case ARG_CASE_SENSITIVE:
|
||||
return log_error("Compiled without pattern matching support");
|
||||
#endif
|
||||
|
||||
@ -973,6 +982,42 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
arg_system_units = strv_free(arg_system_units);
|
||||
}
|
||||
|
||||
|
||||
#if HAVE_PCRE2
|
||||
if (arg_pattern) {
|
||||
unsigned flags;
|
||||
|
||||
if (arg_case_sensitive >= 0)
|
||||
flags = !arg_case_sensitive * PCRE2_CASELESS;
|
||||
else {
|
||||
_cleanup_(pcre2_match_data_freep) pcre2_match_data *md = NULL;
|
||||
bool has_case;
|
||||
_cleanup_(pcre2_code_freep) pcre2_code *cs = NULL;
|
||||
|
||||
md = pcre2_match_data_create(1, NULL);
|
||||
if (!md)
|
||||
return log_oom();
|
||||
|
||||
r = pattern_compile("[[:upper:]]", 0, &cs);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = pcre2_match(cs, (PCRE2_SPTR8) arg_pattern, PCRE2_ZERO_TERMINATED, 0, 0, md, NULL);
|
||||
has_case = r >= 0;
|
||||
|
||||
flags = !has_case * PCRE2_CASELESS;
|
||||
}
|
||||
|
||||
log_debug("Doing case %s matching based on %s",
|
||||
flags & PCRE2_CASELESS ? "insensitive" : "sensitive",
|
||||
arg_case_sensitive >= 0 ? "request" : "pattern casing");
|
||||
|
||||
r = pattern_compile(arg_pattern, flags, &arg_compiled_pattern);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -2525,7 +2570,7 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
#if HAVE_PCRE2
|
||||
if (arg_pattern) {
|
||||
if (arg_compiled_pattern) {
|
||||
_cleanup_(pcre2_match_data_freep) pcre2_match_data *md = NULL;
|
||||
const void *message;
|
||||
size_t len;
|
||||
@ -2547,7 +2592,7 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
assert_se(message = startswith(message, "MESSAGE="));
|
||||
|
||||
r = pcre2_match(arg_pattern,
|
||||
r = pcre2_match(arg_compiled_pattern,
|
||||
message,
|
||||
len - strlen("MESSAGE="),
|
||||
0, /* start at offset 0 in the subject */
|
||||
@ -2631,8 +2676,8 @@ finish:
|
||||
free(arg_verify_key);
|
||||
|
||||
#if HAVE_PCRE2
|
||||
if (arg_pattern)
|
||||
pcre2_code_free(arg_pattern);
|
||||
if (arg_compiled_pattern)
|
||||
pcre2_code_free(arg_compiled_pattern);
|
||||
#endif
|
||||
|
||||
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||
|
@ -500,7 +500,6 @@ tests += [
|
||||
[],
|
||||
'', 'manual'],
|
||||
|
||||
|
||||
[['src/test/test-cgroup-mask.c',
|
||||
'src/test/test-helper.c'],
|
||||
[libcore,
|
||||
|
Loading…
Reference in New Issue
Block a user