[anon] add an anonymizer to help with support requests

Fixes #1055
pull/1062/head
Tim Stack 2 years ago
parent fadcea4403
commit eb0bd4ac9a

@ -7,6 +7,15 @@ lnav v0.11.1:
- Each regex must have a corresponding sample log message
that it matches.
- Each sample must be matched by only one regex.
* Added built-in support for anonymizing content. The
`:write-*` commands now accept an `--anonymize` option
and there is an `anonymize()` SQL function. The
anonymization process will try to replace identifying
information with random data. For example, IPv4 addresses
are replaced with addresses in the 10.0.0.0/8 range.
(This feature is mainly intended to help with providing
information to lnav support that does not have sensitive
values.)
Breaking changes:
* The regexp_capture() table-valued-function now returns NULL

@ -76,6 +76,56 @@ an error message in the status bar, like so:
This makes it easier to run **lnav** in restricted environments without the
risk of privilege escalation.
I/O Commands
------------
Anonymization
^^^^^^^^^^^^^
Anonymization is the process of removing identifying information from content
to make it safer for sharing with others. For example, an IP address can
often be used to uniquely identify an entity. Substituting all instances of
a particular IP with the same dummy value would remove the identifying data
without losing statistical accuracy. **lnav** has built-in support for
anonymization through the :code:`--anonymize` flag on the :code:`:write-*`
collection of commands. While the anonymization process should catch most
:IPv4 Addresses: Are replaced with addresses in the :code:`10.0.0.0/8` range.
:IPv6 Addresses: Are replaced with addresses in the :code:`2001:db8::/32` range.
:URL User Names: Are replaced with a random animal name.
:URL Passwords: Are replaced with a hash of the input password.
:URL Hosts: Are replaced with a random name under the example.com domain.
:URL Paths: Are recursively examined for substitution.
:URL Query Strings: Are recursively examined for substitution.
:URL Fragments: Are recursively examined for substitution.
:Paths: Are recursively examined for substitution.
:Credit Card Numbers: Are replaced with a 16 digit hash of the input number.
:MAC Addresses: Are replaced with addresses in the :code:`00:00:5E:00:53:00` range.
:Hex Dumps: Are replaced with a hash of the input replicated to the size of input.
:Email User Names: Are replaced with a random animal name.
:Email Host Names: Are replaced with a random name under the example.com domain.
:Words: Are replaced with a random word with a matching case style.
:Quoted Strings: Are recursively examined for substitution.
:UUID: Are replaced with a hash of the input.
:XML Attribute Values: Are recursively examined for substitution.
Reference
---------

@ -102,7 +102,7 @@ function(bin2c)
DEPENDS bin2c "${FILE_TO_LINK}")
endfunction(bin2c)
foreach (FILE_TO_LINK ansi-palette.json emojis.json xml-entities.json xterm-palette.json help.txt help.md init.sql)
foreach (FILE_TO_LINK animals.json ansi-palette.json diseases.json emojis.json xml-entities.json xterm-palette.json help.txt help.md init.sql words.json)
string(REPLACE "." "-" DST_FILE "${FILE_TO_LINK}")
add_custom_command(
OUTPUT "${DST_FILE}.h" "${DST_FILE}.cc"
@ -419,6 +419,7 @@ add_library(
sqlitepp.cc
state-extension-functions.cc
styling.cc
text_anonymizer.cc
text_format.cc
textfile_highlighters.cc
textfile_sub_source.cc
@ -535,6 +536,7 @@ add_library(
sysclip.cfg.hh
term_extra.hh
termios_guard.hh
text_anonymizer.hh
text_format.hh
textfile_highlighters.hh
textfile_sub_source.hh

@ -91,12 +91,15 @@ if HAVE_RE2C
endif
LNAV_BUILT_FILES = \
animals-json.cc \
ansi-palette-json.cc \
builtin-scripts.cc \
builtin-sh-scripts.cc \
default-config.cc \
default-formats.cc \
diseases-json.cc \
emojis-json.cc \
words-json.cc \
help-md.cc \
init-sql.cc \
time_fmts.cc \
@ -158,12 +161,15 @@ LDADD = \
dist_noinst_DATA = \
alpha-release.sh \
animals.json \
ansi-palette.json \
diseases.json \
emojis.json \
$(BUILTIN_LNAVSCRIPTS) \
$(BUILTIN_SHSCRIPTS) \
$(CONFIG_FILES) \
$(FORMAT_FILES) \
words.json \
xml-entities.json \
xterm-palette.json
@ -295,6 +301,7 @@ noinst_HEADERS = \
sysclip.cfg.hh \
termios_guard.hh \
term_extra.hh \
text_anonymizer.hh \
text_format.hh \
textfile_highlighters.hh \
textfile_sub_source.hh \
@ -444,6 +451,7 @@ libdiag_a_SOURCES = \
statusview_curses.cc \
string-extension-functions.cc \
styling.cc \
text_anonymizer.cc \
text_format.cc \
textfile_sub_source.cc \
timer.cc \
@ -502,12 +510,15 @@ CLEANFILES = \
DISTCLEANFILES = \
$(LNAV_BUILT_FILES) \
animals-json.h \
ansi-palette-json.h \
builtin-scripts.h \
builtin-sh-scripts.h \
default-config.h \
default-formats.h \
diseases-json.h \
emojis-json.h \
words-json.h \
help-md.h \
init-sql.h \
time_fmts.h \

@ -0,0 +1 @@
{"data":["meerkat","aardvark","addax","alligator","alpaca","anteater","antelope","aoudad","ape","argali","armadillo","baboon","badger","basilisk","bat","bear","beaver","bighorn","bison","boar","budgerigar","buffalo","bull","bunny","burro","camel","canary","capybara","cat","chameleon","chamois","cheetah","chimpanzee","chinchilla","chipmunk","civet","coati","colt","cougar","cow","coyote","crocodile","crow","deer","dingo","doe","dung-beetle","dog","donkey","dormouse","dromedary","duckbill-platypus","dugong","eland","elephant","elk","ermine","ewe","fawn","ferret","finch","fish","fox","frog","gazelle","gemsbok","gila-monster","giraffe","gnu","goat","gopher","gorilla","grizzly-bear","ground-hog","guanaco","guinea-pig","hamster","hare","hartebeest","hedgehog","highland-cow","hippopotamus","hog","horse","hyena","ibex","iguana","impala","jackal","jaguar","jerboa","kangaroo","kitten","koala","lamb","lemur","leopard","lion","lizard","llama","lovebird","lynx","mandrill","mare","marmoset","marten","mink","mole","mongoose","monkey","moose","mountain-goat","mouse","mule","musk-deer","musk-ox","muskrat","mustang","mynah-bird","newt","ocelot","okapi","opossum","orangutan","oryx","otter","ox","panda","panther","parakeet","parrot","peccary","pig","octopus","thorny-devil","starfish","blue-crab","snowy-owl","chicken","rooster","bumble-bee","eagle-owl","polar-bear","pony","porcupine","porpoise","prairie-dog","pronghorn","puma","puppy","quagga","rabbit","raccoon","ram","rat","reindeer","rhinoceros","salamander","seal","sheep","shrew","silver-fox","skunk","sloth","snake","springbok","squirrel","stallion","steer","tapir","tiger","toad","turtle","vicuna","walrus","warthog","waterbuck","weasel","whale","wildcat","bald-eagle","wolf","wolverine","wombat","woodchuck","yak","zebra","zebu"]}

@ -36,6 +36,7 @@
#include <string.h>
#include "config.h"
#include "pcrepp/pcre2pp.hh"
#include "xxHash/xxhash.h"
const static int TABLE_SIZE = 4095;
@ -244,3 +245,59 @@ string_fragment::utf8_length() const
return Ok(retval);
}
string_fragment::case_style
string_fragment::detect_text_case_style() const
{
static const auto LOWER_RE
= lnav::pcre2pp::code::from_const(R"(^[^A-Z]+$)");
static const auto UPPER_RE
= lnav::pcre2pp::code::from_const(R"(^[^a-z]+$)");
static const auto CAMEL_RE
= lnav::pcre2pp::code::from_const(R"(^(?:[A-Z][a-z0-9]+)+$)");
if (LOWER_RE.find_in(*this).ignore_error().has_value()) {
return case_style::lower;
}
if (UPPER_RE.find_in(*this).ignore_error().has_value()) {
return case_style::upper;
}
if (CAMEL_RE.find_in(*this).ignore_error().has_value()) {
return case_style::camel;
}
return case_style::mixed;
}
std::string
string_fragment::to_string_with_case_style(case_style style) const
{
std::string retval;
switch (style) {
case case_style::lower: {
for (auto ch : *this) {
retval.append(1, std::tolower(ch));
}
break;
}
case case_style::upper: {
for (auto ch : *this) {
retval.append(1, std::toupper(ch));
}
break;
}
case case_style::camel: {
retval = this->to_string();
if (!this->empty()) {
retval[0] = toupper(retval[0]);
}
break;
}
case case_style::mixed: {
return this->to_string();
}
}
return retval;
}

@ -523,6 +523,17 @@ struct string_fragment {
return scn::string_view{this->begin(), this->end()};
}
enum class case_style {
lower,
upper,
camel,
mixed,
};
case_style detect_text_case_style() const;
std::string to_string_with_case_style(case_style style) const;
const char* sf_string;
int sf_begin;
int sf_end;

@ -38,13 +38,25 @@
#include "base/lnav_log.hh"
#include "fmt/format.h"
#include "optional.hpp"
template<size_t COUNT, typename T = unsigned char>
struct byte_array {
static constexpr size_t BYTE_COUNT = COUNT * sizeof(T);
static constexpr size_t STRING_SIZE = BYTE_COUNT * 2 + 1;
byte_array() {}
byte_array() = default;
static byte_array from(std::initializer_list<T> bytes)
{
byte_array retval;
size_t index = 0;
for (const auto by : bytes) {
retval.ba_data[index++] = by;
}
return retval;
}
byte_array(const byte_array& other)
{
@ -69,19 +81,47 @@ struct byte_array {
void clear() { memset(this->ba_data, 0, BYTE_COUNT); }
template<typename OutputIt>
void to_string(OutputIt out) const
void to_string(OutputIt out,
nonstd::optional<char> separator = nonstd::nullopt) const
{
for (size_t lpc = 0; lpc < BYTE_COUNT; lpc++) {
if (lpc > 0 && separator) {
*out = separator.value();
}
fmt::format_to(out, FMT_STRING("{:02x}"), this->ba_data[lpc]);
}
}
std::string to_string() const
std::string to_uuid_string() const
{
return fmt::format(
FMT_STRING("{:02x}{:02x}{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-"
"{:02x}{:02x}-{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}"),
this->ba_data[0 % BYTE_COUNT],
this->ba_data[1 % BYTE_COUNT],
this->ba_data[2 % BYTE_COUNT],
this->ba_data[3 % BYTE_COUNT],
this->ba_data[4 % BYTE_COUNT],
this->ba_data[5 % BYTE_COUNT],
this->ba_data[6 % BYTE_COUNT],
this->ba_data[7 % BYTE_COUNT],
this->ba_data[8 % BYTE_COUNT],
this->ba_data[9 % BYTE_COUNT],
this->ba_data[10 % BYTE_COUNT],
this->ba_data[11 % BYTE_COUNT],
this->ba_data[12 % BYTE_COUNT],
this->ba_data[13 % BYTE_COUNT],
this->ba_data[14 % BYTE_COUNT],
this->ba_data[15 % BYTE_COUNT]);
}
std::string to_string(nonstd::optional<char> separator
= nonstd::nullopt) const
{
std::string retval;
retval.reserve(STRING_SIZE);
this->to_string(std::back_inserter(retval));
this->to_string(std::back_inserter(retval), separator);
return retval;
}
@ -94,7 +134,7 @@ struct byte_array {
return &ptr[offset];
}
unsigned char ba_data[BYTE_COUNT];
unsigned char ba_data[BYTE_COUNT]{};
};
template<size_t COUNT, typename T = unsigned char>

@ -60,6 +60,9 @@ static struct {
{
"time",
},
{
"dt",
},
/* { "qual", pcrepp("\\A([^\\s:=]+:[^\\s:=,]+(?!,)(?::[^\\s:=,]+)*)"), }, */
{
"ipv6",
@ -110,31 +113,31 @@ static struct {
},
{
"lcurly",
"lcur",
},
{
"rcurly",
"rcur",
},
{
"lsquare",
"lsqu",
},
{
"rsquare",
"rsqu",
},
{
"lparen",
"lpar",
},
{
"rparen",
"rpar",
},
{
"langle",
"lang",
},
{
"rangle",
"rang",
},
{
@ -145,6 +148,9 @@ static struct {
"uuid",
},
{
"cc",
},
{
"vers",
},
@ -203,7 +209,6 @@ const char* DNT_NAMES[DNT_MAX - DNT_KEY] = {
"meas",
"var",
"rang",
"dt",
"grp",
};
@ -221,3 +226,38 @@ data_scanner::token2name(data_token_t token)
}
return DNT_NAMES[token - DNT_KEY];
}
bool
data_scanner::is_credit_card(string_fragment cc) const
{
auto cc_no_spaces = cc.to_string();
auto new_end = std::remove_if(cc_no_spaces.begin(),
cc_no_spaces.end(),
[](auto ch) { return ch == ' '; });
cc_no_spaces.erase(new_end, cc_no_spaces.end());
int len = cc_no_spaces.size();
int double_even_sum = 0;
// Step 1: double every second digit, starting from right.
// if results in 2 digit number, add the digits to obtain single digit
// number. sum all answers to obtain 'double_even_sum'
for (int lpc = len - 2; lpc >= 0; lpc = lpc - 2) {
int dbl = ((cc_no_spaces[lpc] - '0') * 2);
if (dbl > 9) {
dbl = (dbl / 10) + (dbl % 10);
}
double_even_sum += dbl;
}
// Step 2: add every odd placed digit from right to double_even_sum's value
for (int lpc = len - 1; lpc >= 0; lpc = lpc - 2) {
double_even_sum += (cc_no_spaces[lpc] - 48);
}
// Step 3: check if final 'double_even_sum' is multiple of 10
// if yes, it is valid.
return double_even_sum % 10 == 0;
}

@ -44,6 +44,7 @@ enum data_token_t {
DT_MAC_ADDRESS,
DT_DATE,
DT_TIME,
DT_DATE_TIME,
DT_IPV6_ADDRESS,
DT_HEX_DUMP,
DT_XML_DECL_TAG,
@ -79,6 +80,7 @@ enum data_token_t {
DT_IPV4_ADDRESS,
DT_UUID,
DT_CREDIT_CARD_NUMBER,
DT_VERSION_NUMBER,
DT_OCTAL_NUMBER,
DT_PERCENTAGE,
@ -107,7 +109,6 @@ enum data_token_t {
DNT_MEASUREMENT,
DNT_VARIABLE_KEY,
DNT_ROWRANGE,
DNT_DATE_TIME,
DNT_GROUP,
DNT_MAX,
@ -198,6 +199,8 @@ public:
}
private:
bool is_credit_card(string_fragment frag) const;
std::string ds_line;
shared_buffer_ref ds_sbr;
string_fragment ds_input;

File diff suppressed because it is too large Load Diff

@ -31,6 +31,7 @@
#include <netinet/in.h>
#include <sys/socket.h>
#include "base/date_time_scanner.hh"
#include "config.h"
#include "data_scanner.hh"
@ -56,6 +57,38 @@ nonstd::optional<data_scanner::tokenize_result> data_scanner::tokenize2()
return tokenize_result{token_out, cap_all, cap_inner, this->ds_input.data()}; \
}
static const unsigned char *EMPTY = (const unsigned char *) "";
if (this->ds_next_offset < this->ds_input.length()) {
date_time_scanner dts;
struct exttm tm;
struct timeval tv;
auto dt_end = dts.scan(this->ds_input.data() + this->ds_next_offset,
this->ds_input.length() - this->ds_next_offset,
nullptr,
&tm,
tv);
if (dt_end != nullptr &&
!(tm.et_flags & ETF_MACHINE_ORIENTED) &&
(tm.et_flags & ETF_DAY_SET ||
(tm.et_flags & ETF_HOUR_SET && tm.et_flags & ETF_MINUTE_SET))) {
cap_all.c_begin = this->ds_next_offset;
cap_inner.c_begin = this->ds_next_offset;
this->ds_next_offset = dt_end - this->ds_input.data();
cap_all.c_end = this->ds_next_offset;
cap_inner.c_end = this->ds_next_offset;
if (tm.et_flags & ETF_DAY_SET) {
if (tm.et_flags & ETF_MINUTE_SET) {
token_out = DT_DATE_TIME;
} else {
token_out = DT_DATE;
}
} else {
token_out = DT_TIME;
}
return tokenize_result{token_out, cap_all, cap_inner, this->ds_input.data()};
}
}
struct _YYCURSOR {
YYCTYPE operator*() const {
if (this->val < this->lim) {
@ -169,8 +202,8 @@ nonstd::optional<data_scanner::tokenize_result> data_scanner::tokenize2()
("/"|"./"|"../"|[A-Z]":\\"|"\\\\")("Program Files"(" (x86)")?)?[a-zA-Z0-9_\.\-\~/\\!@#$%^&*()]* { RET(DT_PATH); }
(SPACE|NUM)NUM":"NUM{2}/[^:] { RET(DT_TIME); }
(SPACE|NUM)NUM?":"NUM{2}":"NUM{2}("."NUM{3,6})?/[^:] { RET(DT_TIME); }
[0-9a-fA-F][0-9a-fA-F](":"[0-9a-fA-F][0-9a-fA-F])+ {
if ((YYCURSOR - this->ds_input.udata()) == 17) {
[0-9a-fA-F][0-9a-fA-F]((":"|"-")[0-9a-fA-F][0-9a-fA-F])+ {
if ((YYCURSOR.val - (this->ds_input.udata() + this->ds_next_offset)) == 17) {
RET(DT_MAC_ADDRESS);
} else {
RET(DT_HEX_DUMP);
@ -225,6 +258,19 @@ nonstd::optional<data_scanner::tokenize_result> data_scanner::tokenize2()
[0-9a-fA-F]{8}("-"[0-9a-fA-F]{4}){3}"-"[0-9a-fA-F]{12} { RET(DT_UUID); }
(NUM{4}" "NUM{4}" "NUM{4}" "NUM{4}|NUM{16})/[^0-9] {
CAPTURE(DT_CREDIT_CARD_NUMBER);
if (!this->is_credit_card(this->to_string_fragment(cap_all))) {
if (cap_all.length() > 16) {
cap_all.c_end = cap_all.c_begin + 4;
cap_inner.c_end = cap_inner.c_begin + 4;
}
this->ds_next_offset = cap_all.c_end;
token_out = DT_NUMBER;
}
return tokenize_result{token_out, cap_all, cap_inner, this->ds_input.data()};
}
[0-9]"."[0-9]+'e'[\-\+][0-9]+ { RET(DT_NUMBER); }
[0-9]+("."[0-9]+[a-zA-Z0-9_]*){2,}("-"[a-zA-Z0-9_]+)?|[0-9]+("."[0-9]+[a-zA-Z0-9_]*)+"-"[a-zA-Z0-9_]+ {

@ -0,0 +1,549 @@
{
"data": [
"achondroplasia",
"acinetobacter-infections",
"acne",
"actinomycosis",
"addisons-disease",
"african-sleeping-sickness",
"agammaglobulinemia",
"albinism",
"alcoholic-hepatitis",
"allergy",
"alopecia",
"alopecia-areata",
"alzheimers-disease",
"amblyopia",
"amebiasis",
"ampylobacter-infection",
"amyloidosis",
"anaplasmosis",
"anemia",
"aneurdu",
"ankylosing-spondylitis",
"anorexia",
"anosmia",
"anotia",
"anthrax",
"anti-gbm",
"anti-tbm-nephritis",
"antiphospholipid-syndrome",
"appendicitis",
"apraxia",
"arcanobacterium-haemolyticum-infection",
"argentine-hemorrhagic-fever",
"argyria",
"arthritis",
"ascariasis",
"aseptic-meningitis",
"aspergillosis",
"asthenia",
"asthma",
"astigmatism",
"astrovirus-infection",
"atherosclerosis",
"athetosis",
"atrophy",
"autoimmune-angioedema",
"autoimmune-aplastic-anemia",
"autoimmune-dysautonomia",
"autoimmune-hepatitis",
"autoimmune-hyperlipidemia",
"autoimmune-immunodeficiency",
"autoimmune-inner-ear-disease",
"autoimmune-myocarditis",
"autoimmune-oophoritis",
"autoimmune-pancreatitis",
"autoimmune-retinopathy",
"autoimmune-thrombocytopenic-purpura",
"autoimmune-thyroid-disease",
"autoimmune-urticaria",
"axonal-&-neuronal-neuropathies",
"babesiosis",
"bacillary-dysentery",
"bacillus-cereus-infection",
"bacterial-meningitis",
"bacterial-pneumonia",
"bacterial-vaginosis",
"bacteroides-infection",
"balantidiasis",
"balo-disease",
"barbers-itch",
"baylisascaris-infection",
"behcets-disease",
"beriberi",
"bk-virus-infection",
"black-death",
"black-piedra",
"blastocystis-hominis-infection",
"blastomycosis",
"bolivian-hemorrhagic-fever",
"borrelia-infection",
"botulism",
"brazilian-hemorrhagic-fever",
"breast-cancer",
"bronchitis",
"brucellosis",
"bubonic-plague",
"bullous-pemphigoid",
"bunion",
"burkholderia-infection",
"buruli-ulcer",
"calculi",
"calicivirus-infection",
"campylobacteriosis",
"cancer",
"candidiasis",
"carbon-monoxide-poisoning",
"cardiomyopathy",
"castleman-disease",
"cat-scratch-disease",
"celiac-disease",
"celiacs-disease",
"cellulitis",
"cerebral-palsy",
"chagas-disease",
"chalazion",
"chancroid",
"chavia",
"cherubism",
"chickenpox",
"chikungunya",
"chlamydia",
"chlamydia-trachomatis",
"chlamydophila-pneumoniae-infection",
"cholera",
"chordoma",
"chorea",
"chromoblastomycosis",
"chronic-fatigue-syndrome",
"chronic-inflammatory-demyelinating-polyneuropathy",
"chronic-recurrent-multifocal-ostomyelitis",
"churg-strauss-syndrome",
"circadian-rhythm-sleep-disorder",
"clonorchiasis",
"clostridial-myonecrosis",
"clostridium-difficile-infection",
"coccidioidomycosis",
"cogans-syndrome",
"cold-agglutinin-disease",
"colitis",
"colorado-tick-fever",
"common-cold",
"condyloma",
"congenital-heart-block",
"congestive-heart-disease",
"coronary-heart-disease",
"cowpox",
"coxsackie-myocarditis",
"crest-disease",
"cretinism",
"creutzfeldt-jakob-disease",
"crimean-congo-hemorrhagic-fever",
"crohns-disease",
"cryptococcosis",
"cryptosporidiosis",
"cutaneous-larva-migrans",
"cyclosporiasis",
"cysticercosis",
"cytomegalovirus-infection",
"demyelinating-neuropathies",
"dengue-fever",
"dermatitis-herpetiformis",
"dermatomyositis",
"devics-disease",
"diabetes-mellitus",
"dientamoebiasis",
"diphtheria",
"diphyllobothriasis",
"discoid-lupus",
"donovanosis",
"dracunculiasis",
"dresslers-syndrome",
"ear-infection",
"ebola",
"ebola-hemorrhagic-fever",
"echinococcosis",
"ehrlichiosis",
"elephantiasis",
"emphysema",
"encephalitis",
"endometriosis",
"enterovirus-infection",
"eosinophilic-esophagitis",
"eosinophilic-fasciitis",
"epidemic-typhus",
"epilepsy",
"erectile-dysfunctions",
"erythema-infectiosum",
"erythema-nodosum",
"essential-mixed-cryoglobulinemia",
"evans-syndrome",
"exanthem-subitum",
"experimental-allergic-encephalomyelitis",
"fasciolopsiasis",
"fasciolosis",
"fatal-familial-insomnia",
"fibromyalgia",
"fibrosing-alveolitis",
"fifth-disease",
"filariasis",
"foodborne-illness",
"free-living-amebic-infection",
"fusobacterium-infection",
"gangrene",
"gas-gangrene",
"gastroenteritis",
"genital-herpes",
"geotrichosis",
"gerd",
"gerstmann-sträussler-scheinker-syndrome",
"giant-cell-arteritis",
"giant-cell-myocarditis",
"giardiasis",
"glanders",
"glomerulonephritis",
"gnathostomiasis",
"goitre",
"gonorrhea",
"goodpastures-syndrome",
"granuloma-inguinale",
"graves-disease",
"group-a-streptococcal-infection",
"group-b-streptococcal-infection",
"guillain-barre-syndrome",
"haemophilus-influenzae-infection",
"hand-foot-and-mouth-disease",
"hantavirus-pulmonary-syndrome",
"hashimotos-encephalitis",
"hashimotos-thyroiditis",
"heart-disease",
"heartland-virus-disease",
"helicobacter-pylori-infection",
"hemolytic-anemia",
"hemolytic-uremic-syndrome",
"henoch-schonlein-purpura",
"hepatitis-a",
"hepatitis-b",
"hepatitis-c",
"hepatitis-d",
"hepatitis-e",
"herpes-gestationis",
"herpes-simplex",
"histoplasmosis",
"hiv",
"hookworm-infection",
"human-bocavirus-infection",
"human-ewingii-ehrlichiosis",
"human-granulocytic-anaplasmosis",
"human-metapneumovirus-infection",
"human-monocytic-ehrlichiosis",
"human-papillomavirus-(hpv)",
"human-parainfluenza-virus-infection",
"huntingtons-disease",
"hymenolepiasis",
"hypermetropia",
"hyperopia",
"hyperthyroidism",
"hypogammaglobulinemia",
"hypothyroid",
"hypotonia",
"idiopathic-pulmonary-fibrosis",
"idiopathic-thrombocytopenic-purpura",
"iga-nephropathy",
"igg4-related-sclerosing-disease",
"ignious-syndrome",
"immunoregulatory-lipoproteins",
"impetigo",
"inclusion-body-myositis",
"infertility",
"influenza",
"interstitial-cystitis",
"iritis",
"iron-deficiency-anemia",
"irritable-bowel-syndrome",
"isosporiasis",
"jaundice",
"juvenile-arthritis",
"juvenile-diabetes",
"juvenile-myositis",
"kawasaki-disease",
"kawasaki-syndrome",
"keloids",
"keratitis",
"kingella-kingae-infection",
"kuru",
"kwashiorkor",
"lambert-eaton-syndrome",
"laryngitis",
"lassa-fever",
"lead-poisoning",
"legionellosis",
"legionnaires-disease",
"leishmaniasis",
"leprosy",
"leptospirosis",
"leukemia",
"leukocytoclastic-vasculitis",
"lice",
"lichen-planus",
"lichen-sclerosus",
"ligneous-conjunctivitis",
"listeriosis",
"lockjaw",
"loiasis",
"lung-cancer",
"lupus",
"lupus-erythematosus",
"lyme-disease",
"lymphocytic-choriomeningitis",
"lymphogranuloma-venereum",
"lymphoma",
"mad-cow-disease",
"malaria",
"marburg-fever",
"marburg-hemorrhagic-fever",
"mattticular-syndrome",
"measles",
"melanoma",
"melioidosis",
"menieres-disease",
"meningitis",
"meningococcal-disease",
"metagonimiasis",
"metastatic-cancer",
"microscopic-polyangiitis",
"microsporidiosis",
"middle-east-respiratory-syndrome",
"migraine",
"mixed-connective-tissue-disease",
"molluscum-contagiosum",
"monkeypox",
"mononucleosis",
"moorens-ulcer",
"morquio-syndrome",
"mucha-habermann-disease",
"multiple-myeloma",
"multiple-sclerosis",
"mumps",
"murine-typhus",
"muscular-dystrophy",
"myasthenia-gravis",
"mycetoma",
"mycoplasma-pneumonia",
"myelitis",
"myiasis",
"myoclonus",
"myopia",
"myositis",
"myxedema",
"ménières-disease",
"narcolepsy",
"necrotizing-fasciitis",
"neonatal-conjunctivitis",
"neoplasm",
"neuromyelitis-optica",
"neutropenia",
"night-blindness",
"nocardiosis",
"non-gonococcal-urethritis",
"obesity",
"ocular-cicatricial-pemphigoid",
"onchocerciasis",
"optic-neuritis",
"osteoarthritis",
"osteoporosis",
"otitis",
"palindromic-rheumatism",
"paracoccidioidomycosis",
"paragonimiasis",
"paraneoplastic-cerebellar-degeneration",
"paratyphoid-fever",
"parkinsons-disease",
"paroxysmal-nocturnal-hemoglobinuria",
"parry-romberg-syndrome",
"pars-planitis",
"parsonnage-turner-syndrome",
"pasteurellosis",
"pediculosis-capitis-(head-lice)",
"pediculosis-corporis-(body-lice)",
"pediculosis-pubis-(pubic-lice)",
"pelvic-inflammatory-disease",
"pemphigus",
"periodontal-disease",
"peripheral-neuropathy",
"peritonitis",
"perivenous-encephalomyelitis",
"pernicious-anemia",
"pertussis",
"phenylketonuria",
"pilia",
"pinworm-infection",
"plague",
"pneumococcal-infection",
"pneumocystis-pneumonia",
"pneumonia",
"pneumonia",
"poems-syndrome",
"poliomyelitis",
"polyarteritis-nodosa",
"polymyalgia-rheumatica",
"polymyositis",
"pontiac-fever",
"porphyria",
"postmyocardial-infarction-syndrome",
"postpericardiotomy-syndrome",
"prevotella-infection",
"primary-amoebic-meningoencephalitis",
"primary-biliary-cirrhosis",
"primary-sclerosing-cholangitis",
"progeria",
"progesterone-dermatitis",
"progressive-multifocal-leukoencephalopathy",
"prostatitis",
"psittacosis",
"psoriasis",
"psoriatic-arthritis",
"pubic-lice",
"pulmonary-embolism",
"pure-red-cell-aplasia",
"pyoderma-gangrenosum",
"q-fever",
"ques-fever",
"rabies",
"rat-bite-fever",
"raynauds-phenomenon",
"reactive-arthritis",
"reflex-sympathetic-dystrophy",
"reiters-syndrome",
"relapsing-polychondritis",
"repetitive-strain-injury",
"respiratory-syncytial-virus-infection",
"restless-legs-syndrome",
"retroperitoneal-fibrosis",
"rheumatic-fever",
"rheumatic-heart",
"rheumatism",
"rheumatoid-arthritis",
"rhinosporidiosis",
"rhinovirus-infection",
"rickets",
"rickettsial-infection",
"rickettsialpox",
"rift-valley-fever",
"ringworm",
"river-blindness",
"rocky-mountain-spotted-fever",
"rotavirus-infection",
"rubella",
"salmonellosis",
"sarcoidosis",
"sars",
"scabies",
"scarlet-fever",
"schistosomiasis",
"schizophrenia",
"schmidt-syndrome",
"sciatica",
"scleritis",
"scleroderma",
"scrapie",
"scurvy",
"sepsis",
"septicemia",
"shigellosis",
"shin-splints",
"shingles",
"sickle-cell-anemia",
"siderosis",
"sids",
"silicosis",
"sixth-disease",
"sjogrens-syndrome",
"smallpox",
"south-american-blastomycosis",
"sperm-&-testicular-autoimmunity",
"sporotrichosis",
"staphylococcal-food-poisoning",
"staphylococcal-infection",
"stevens-johnson-syndrome",
"stiff-person-syndrome",
"stomach-flu",
"stomach-ulcers",
"strabismus",
"strep-throat",
"streptococcal-infection",
"strongyloidiasis",
"subacute-bacterial-endocarditis",
"subacute-sclerosing-panencephalitis",
"susacs-syndrome",
"swine-influenza",
"sympathetic-ophthalmia",
"synovitis",
"syphilis",
"taeniasis",
"takayasus-arteritis",
"tay-sachs-disease",
"temporal-arteritis/giant-cell-arteritis",
"tennis-elbow",
"teratoma",
"tetanus",
"thalassaemia",
"thrombocytopenic-purpura",
"thrush",
"thymoma",
"tinea-barbae",
"tinnitus",
"tolosa-hunt-syndrome",
"tonsillitis",
"tooth-decay",
"toxic-shock-syndrome",
"toxocariasis",
"transverse-myelitis",
"trichinosis",
"trichomoniasis",
"trichuriasis",
"trinochccliasis",
"trisomy",
"tuberculosis",
"tularemia",
"tumor",
"tungiasis",
"type-1-diabetes",
"typhoid-fever",
"typhus",
"ulcerative-colitis",
"ulcers",
"undifferentiated-connective-tissue-disease",
"ureaplasma-urealyticum-infection",
"uremia",
"urticaria",
"uveitis",
"valley-fever",
"varicella",
"varicose-veins",
"vasculitis",
"vasovagal-syncope",
"venezuelan-equine-encephalitis",
"venezuelan-hemorrhagic-fever",
"vesiculobullous-dermatosis",
"viral-fever",
"viral-meningitis",
"viral-pneumonia",
"vitiligo",
"von-hippel-lindau-disease",
"warkany-syndrome",
"warts",
"watkins",
"wegeners-granulomatosis",
"west-nile-fever",
"whipworm-infection",
"white-piedra",
"whitmores-disease",
"whooping-cough",
"yellow-fever",
"yersinia-pseudotuberculosis-infection",
"yersiniosis",
"zygomycosis"
]
}

@ -34,6 +34,7 @@ logfmt_parser_test_SOURCES = \
logfmt_parser_test_LDADD = \
liblogfmt.a \
$(top_builddir)/src/base/libbase.a \
$(top_builddir)/src/pcrepp/libpcrepp.a \
$(top_builddir)/src/third-party/scnlib/src/libscnlib.a
TESTS = \

@ -1415,12 +1415,13 @@
.. _write_table_to:
:write-table-to *path*
^^^^^^^^^^^^^^^^^^^^^^
:write-table-to *\[--anonymize\]* *path*
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Write SQL results to the given file in a tabular format
**Parameters**
* **--anonymize** --- Anonymize the table contents
* **path\*** --- The path to the file to write
**Examples**
@ -1438,12 +1439,13 @@
.. _write_csv_to:
:write-csv-to *path*
^^^^^^^^^^^^^^^^^^^^
:write-csv-to *\[--anonymize\]* *path*
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Write SQL results to the given file in CSV format
**Parameters**
* **--anonymize** --- Anonymize the row contents
* **path\*** --- The path to the file to write
**Examples**
@ -1461,12 +1463,13 @@
.. _write_json_to:
:write-json-to *path*
^^^^^^^^^^^^^^^^^^^^^
:write-json-to *\[--anonymize\]* *path*
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Write SQL results to the given file in JSON format
**Parameters**
* **--anonymize** --- Anonymize the JSON values
* **path\*** --- The path to the file to write
**Examples**
@ -1484,12 +1487,13 @@
.. _write_jsonlines_to:
:write-jsonlines-to *path*
^^^^^^^^^^^^^^^^^^^^^^^^^^
:write-jsonlines-to *\[--anonymize\]* *path*
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Write SQL results to the given file in JSON Lines format
**Parameters**
* **--anonymize** --- Anonymize the JSON values
* **path\*** --- The path to the file to write
**Examples**
@ -1507,13 +1511,14 @@
.. _write_raw_to:
:write-raw-to *\[--view={log,db}\]* *path*
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
:write-raw-to *\[--view={log,db}\]* *\[--anonymize\]* *path*
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
In the log view, write the original log file content of the marked messages to the file. In the DB view, the contents of the cells are written to the output file.
**Parameters**
* **--view={log,db}** --- The view to use as the source of data
* **--anonymize** --- Anonymize the lines
* **path\*** --- The path to the file to write
**Examples**
@ -1531,12 +1536,13 @@
.. _write_screen_to:
:write-screen-to *path*
^^^^^^^^^^^^^^^^^^^^^^^
:write-screen-to *\[--anonymize\]* *path*
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Write the displayed text or SQL results to the given file without any formatting
**Parameters**
* **--anonymize** --- Anonymize the lines
* **path\*** --- The path to the file to write
**Examples**
@ -1554,12 +1560,13 @@
.. _write_to:
:write-to *path*
^^^^^^^^^^^^^^^^
:write-to *\[--anonymize\]* *path*
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Overwrite the given file with any marked lines in the current view
**Parameters**
* **--anonymize** --- Anonymize the lines
* **path\*** --- The path to the file to write
**Examples**
@ -1577,12 +1584,13 @@
.. _write_view_to:
:write-view-to *path*
^^^^^^^^^^^^^^^^^^^^^
:write-view-to *\[--anonymize\]* *path*
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Write the text in the top view to the given file without any formatting
**Parameters**
* **--anonymize** --- Anonymize the lines
* **path\*** --- The path to the file to write
**Examples**

@ -480,6 +480,30 @@ acosh(*num*)
----
.. _anonymize:
anonymize(*value*)
^^^^^^^^^^^^^^^^^^
Replace identifying information with random values.
**Parameters**
* **value\*** --- The text to anonymize
**Examples**
To anonymize an IP address:
.. code-block:: custsqlite
;SELECT anonymize('Hello, 192.168.1.2')
Aback, 10.0.0.1
**See Also**
:ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
----
.. _asin:
asin(*num*)
@ -772,7 +796,7 @@ char(*X*)
HI
**See Also**
:ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
:ref:`anonymize`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
----
@ -805,7 +829,7 @@ charindex(*needle*, *haystack*, *\[start\]*)
0
**See Also**
:ref:`char`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
:ref:`anonymize`, :ref:`char`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
----
@ -973,7 +997,7 @@ decode(*value*, *algorithm*)
curl
**See Also**
:ref:`char`, :ref:`charindex`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
:ref:`anonymize`, :ref:`char`, :ref:`charindex`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
----
@ -1117,7 +1141,7 @@ encode(*value*, *algorithm*)
Hello%2C%20World%21
**See Also**
:ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
:ref:`anonymize`, :ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
----
@ -1149,7 +1173,7 @@ endswith(*str*, *suffix*)
0
**See Also**
:ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
:ref:`anonymize`, :ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
----
@ -1204,7 +1228,7 @@ extract(*str*)
{"col_0":1.0,"col_1":2.0}
**See Also**
:ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
:ref:`anonymize`, :ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
----
@ -1405,7 +1429,7 @@ group_concat(*X*, *\[sep\]*)
hw,gw
**See Also**
:ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
:ref:`anonymize`, :ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
----
@ -1429,7 +1453,7 @@ group_spooky_hash(*str*)
4e7a190aead058cb123c94290f29c34a
**See Also**
:ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
:ref:`anonymize`, :ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
----
@ -1445,7 +1469,7 @@ gunzip(*b*)
* **b** --- The blob to decompress
**See Also**
:ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
:ref:`anonymize`, :ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
----
@ -1461,7 +1485,7 @@ gzip(*value*)
* **value** --- The value to compress
**See Also**
:ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
:ref:`anonymize`, :ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
----
@ -1514,7 +1538,7 @@ humanize_duration(*secs*)
1s500
**See Also**
:ref:`char`, :ref:`charindex`, :ref:`date`, :ref:`datetime`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`julianday`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`strftime`, :ref:`substr`, :ref:`time`, :ref:`timediff`, :ref:`timeslice`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
:ref:`anonymize`, :ref:`char`, :ref:`charindex`, :ref:`date`, :ref:`datetime`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`julianday`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`strftime`, :ref:`substr`, :ref:`time`, :ref:`timediff`, :ref:`timeslice`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
----
@ -1538,7 +1562,7 @@ humanize_file_size(*value*)
10.0MB
**See Also**
:ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
:ref:`anonymize`, :ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
----
@ -1586,7 +1610,7 @@ instr(*haystack*, *needle*)
2
**See Also**
:ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
:ref:`anonymize`, :ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
----
@ -1939,7 +1963,7 @@ leftstr(*str*, *N*)
abc
**See Also**
:ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
:ref:`anonymize`, :ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
----
@ -1963,7 +1987,7 @@ length(*str*)
3
**See Also**
:ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
:ref:`anonymize`, :ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
----
@ -2153,7 +2177,7 @@ logfmt2json(*str*)
{"foo":1,"bar":2,"name":"Rolo Tomassi"}
**See Also**
:ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
:ref:`anonymize`, :ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
----
@ -2177,7 +2201,7 @@ lower(*str*)
abc
**See Also**
:ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
:ref:`anonymize`, :ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
----
@ -2209,7 +2233,7 @@ ltrim(*str*, *\[chars\]*)
c
**See Also**
:ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
:ref:`anonymize`, :ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
----
@ -2366,7 +2390,7 @@ padc(*str*, *len*)
abcdef ghi
**See Also**
:ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
:ref:`anonymize`, :ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
----
@ -2398,7 +2422,7 @@ padl(*str*, *len*)
abcdef
**See Also**
:ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
:ref:`anonymize`, :ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
----
@ -2430,7 +2454,7 @@ padr(*str*, *len*)
abcdefghi
**See Also**
:ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
:ref:`anonymize`, :ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
----
@ -2528,7 +2552,7 @@ printf(*format*, *X*)
value: 00011
**See Also**
:ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
:ref:`anonymize`, :ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
----
@ -2552,7 +2576,7 @@ proper(*str*)
Hello, World!
**See Also**
:ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
:ref:`anonymize`, :ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
----
@ -2735,7 +2759,7 @@ regexp_capture(*string*, *pattern*)
1 2 <NULL> 3 8 9 2
**See Also**
:ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
:ref:`anonymize`, :ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
----
@ -2763,7 +2787,7 @@ regexp_capture_into_json(*string*, *pattern*, *\[options\]*)
1 {"col_0":"b","col_1":2}
**See Also**
:ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
:ref:`anonymize`, :ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
----
@ -2802,7 +2826,7 @@ regexp_match(*re*, *str*)
{"num":123,"str":"four"}
**See Also**
:ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_replace`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
:ref:`anonymize`, :ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_replace`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
----
@ -2835,7 +2859,7 @@ regexp_replace(*str*, *re*, *repl*)
<123> <abc>
**See Also**
:ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_match`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
:ref:`anonymize`, :ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_match`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
----
@ -2868,7 +2892,7 @@ replace(*str*, *old*, *replacement*)
zbc
**See Also**
:ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
:ref:`anonymize`, :ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
----
@ -2893,7 +2917,7 @@ replicate(*str*, *N*)
abcabcabc
**See Also**
:ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
:ref:`anonymize`, :ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
----
@ -2917,7 +2941,7 @@ reverse(*str*)
cba
**See Also**
:ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
:ref:`anonymize`, :ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
----
@ -2949,7 +2973,7 @@ rightstr(*str*, *N*)
abc
**See Also**
:ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
:ref:`anonymize`, :ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
----
@ -3045,7 +3069,7 @@ rtrim(*str*, *\[chars\]*)
a
**See Also**
:ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
:ref:`anonymize`, :ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
----
@ -3115,7 +3139,7 @@ sparkline(*value*, *\[upper\]*)
▁▂▃▄▅▆▇█
**See Also**
:ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
:ref:`anonymize`, :ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
----
@ -3160,7 +3184,7 @@ spooky_hash(*str*)
f96b3d9c1a19f4394c97a1b79b1880df
**See Also**
:ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
:ref:`anonymize`, :ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
----
@ -3274,7 +3298,7 @@ startswith(*str*, *prefix*)
0
**See Also**
:ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
:ref:`anonymize`, :ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
----
@ -3299,7 +3323,7 @@ strfilter(*source*, *include*)
bcbc
**See Also**
:ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
:ref:`anonymize`, :ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
----
@ -3386,7 +3410,7 @@ substr(*str*, *start*, *\[size\]*)
b
**See Also**
:ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
:ref:`anonymize`, :ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
----
@ -3593,7 +3617,7 @@ trim(*str*, *\[chars\]*)
abc
**See Also**
:ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
:ref:`anonymize`, :ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`unicode`, :ref:`upper`, :ref:`xpath`
----
@ -3646,7 +3670,7 @@ unicode(*X*)
97
**See Also**
:ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`upper`, :ref:`xpath`
:ref:`anonymize`, :ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`upper`, :ref:`xpath`
----
@ -3684,7 +3708,7 @@ upper(*str*)
ABC
**See Also**
:ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`xpath`
:ref:`anonymize`, :ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`xpath`
----
@ -3727,7 +3751,7 @@ xpath(*xpath*, *xmldoc*)
Hello ★ /abc/def/text() {} Hello ★
**See Also**
:ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`
:ref:`anonymize`, :ref:`char`, :ref:`charindex`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_file_size`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`
----

@ -79,6 +79,7 @@
#include "sqlite-extension-func.hh"
#include "sysclip.hh"
#include "tailer/tailer.looper.hh"
#include "text_anonymizer.hh"
#include "url_loader.hh"
#include "yajl/api/yajl_parse.h"
#include "yajlpp/json_op.hh"
@ -871,9 +872,9 @@ yajl_writer(void* context, const char* str, size_t len)
}
static void
json_write_row(yajl_gen handle, int row)
json_write_row(yajl_gen handle, int row, lnav::text_anonymizer& ta, bool anonymize)
{
db_label_source& dls = lnav_data.ld_db_row_source;
auto& dls = lnav_data.ld_db_row_source;
yajlpp_map obj_map(handle);
for (size_t col = 0; col < dls.dls_headers.size(); col++) {
@ -884,7 +885,7 @@ json_write_row(yajl_gen handle, int row)
continue;
}
db_label_source::header_meta& hm = dls.dls_headers[col];
auto& hm = dls.dls_headers[col];
switch (hm.hm_column_type) {
case SQLITE_FLOAT:
@ -952,12 +953,12 @@ json_write_row(yajl_gen handle, int row)
break;
}
default:
obj_map.gen(dls.dls_rows[row][col]);
obj_map.gen(anonymize ? ta.next(string_fragment::from_c_str(dls.dls_rows[row][col])) : dls.dls_rows[row][col]);
break;
}
break;
default:
obj_map.gen(dls.dls_rows[row][col]);
obj_map.gen(anonymize ? ta.next(string_fragment::from_c_str(dls.dls_rows[row][col])) : dls.dls_rows[row][col]);
break;
}
}
@ -972,6 +973,7 @@ com_save_to(exec_context& ec,
const char* mode = "";
std::string fn, retval;
bool to_term = false;
bool anonymize = false;
int (*closer)(FILE*) = fclose;
if (args.empty()) {
@ -988,6 +990,12 @@ com_save_to(exec_context& ec,
return ec.make_error("unable to parse arguments");
}
auto anon_iter = std::find(split_args.begin(), split_args.end(), "--anonymize");
if (anon_iter != split_args.end()) {
split_args.erase(anon_iter);
anonymize = true;
}
auto* tc = *lnav_data.ld_view_stack.top();
auto opt_view_name = find_arg(split_args, "--view");
if (opt_view_name) {
@ -1017,6 +1025,7 @@ com_save_to(exec_context& ec,
auto& dls = lnav_data.ld_db_row_source;
bookmark_vector<vis_line_t> all_user_marks;
lnav::text_anonymizer ta;
if (args[0] == "write-csv-to" || args[0] == "write-json-to"
|| args[0] == "write-jsonlines-to" || args[0] == "write-cols-to"
@ -1111,7 +1120,7 @@ com_save_to(exec_context& ec,
if (!first) {
fprintf(outfile, ",");
}
csv_write_string(outfile, *iter);
csv_write_string(outfile, anonymize ? ta.next(string_fragment::from_c_str(*iter)) : *iter);
first = false;
}
fprintf(outfile, "\n");
@ -1164,16 +1173,18 @@ com_save_to(exec_context& ec,
fprintf(outfile, "\u2502");
auto cell = dls.dls_rows[row][col];
auto cell_byte_len = strlen(cell);
auto cell_length = utf8_string_length(cell, cell_byte_len)
.unwrapOr(cell_byte_len);
auto padding = hdr.hm_column_size - cell_length;
auto cell = std::string(dls.dls_rows[row][col]);
if (anonymize) {
cell = ta.next(cell);
}
auto cell_length = utf8_string_length(cell)
.unwrapOr(cell.size());
auto padding = anonymize ? 1 : hdr.hm_column_size - cell_length;
if (hdr.hm_column_type != SQLITE3_TEXT) {
fprintf(outfile, "%s", std::string(padding, ' ').c_str());
}
fprintf(outfile, "%s", cell);
fprintf(outfile, "%s", cell.c_str());
if (hdr.hm_column_type == SQLITE3_TEXT) {
fprintf(outfile, "%s", std::string(padding, ' ').c_str());
}
@ -1210,7 +1221,7 @@ com_save_to(exec_context& ec,
break;
}
json_write_row(gen, row);
json_write_row(gen, row, ta, anonymize);
line_count += 1;
}
}
@ -1225,7 +1236,7 @@ com_save_to(exec_context& ec,
break;
}
json_write_row(gen, row);
json_write_row(gen, row, ta, anonymize);
yajl_gen_reset(gen, "\n");
line_count += 1;
}
@ -1249,7 +1260,7 @@ com_save_to(exec_context& ec,
auto* los = tc->get_overlay_source();
tc->listview_value_for_rows(*tc, top, rows);
for (const auto& al : rows) {
for (auto& al : rows) {
while (los != nullptr
&& los->list_value_for_overlay(
*tc, y, tc->get_inner_height(), top, ov_al))
@ -1258,6 +1269,10 @@ com_save_to(exec_context& ec,
++y;
}
wrapped_count += vis_line_t((al.length() - 1) / (dim.second - 2));
if (anonymize) {
al.al_attrs.clear();
al.al_string = ta.next(al.al_string);
}
write_line_to(outfile, al);
line_count += 1;
@ -1295,7 +1310,11 @@ com_save_to(exec_context& ec,
}
for (auto& iter : *row_iter) {
fputs(iter, outfile);
if (anonymize) {
fputs(ta.next(string_fragment::from_c_str(iter)).c_str(), outfile);
} else {
fputs(iter, outfile);
}
}
fprintf(outfile, "\n");
@ -1338,7 +1357,13 @@ com_save_to(exec_context& ec,
continue;
}
auto sbr = read_res.unwrap();
fprintf(outfile, "%.*s\n", (int) sbr.length(), sbr.get_data());
if (anonymize) {
auto msg = ta.next(sbr.to_string_fragment().to_string());
fprintf(outfile, "%s\n", msg.c_str());
} else {
fprintf(
outfile, "%.*s\n", (int) sbr.length(), sbr.get_data());
}
line_count += 1;
}
@ -1357,6 +1382,9 @@ com_save_to(exec_context& ec,
std::string line;
tss->text_value_for_line(*tc, lpc, line, text_sub_source::RF_RAW);
if (anonymize) {
line = ta.next(line);
}
fprintf(outfile, "%s\n", line.c_str());
line_count += 1;
@ -1376,6 +1404,10 @@ com_save_to(exec_context& ec,
break;
}
tc->listview_value_for_rows(*tc, *iter, rows);
if (anonymize) {
rows[0].al_attrs.clear();
rows[0].al_string = ta.next(rows[0].al_string);
}
write_line_to(outfile, rows[0]);
auto y = 1_vl;
@ -5162,6 +5194,7 @@ readline_context::command_t STD_COMMANDS[] = {
help_text(":write-to")
.with_summary("Overwrite the given file with any marked lines in the "
"current view")
.with_parameter(help_text("--anonymize", "Anonymize the lines").optional())
.with_parameter(help_text("path", "The path to the file to write"))
.with_tags({"io", "scripting"})
.with_example(
@ -5172,6 +5205,7 @@ readline_context::command_t STD_COMMANDS[] = {
help_text(":write-csv-to")
.with_summary("Write SQL results to the given file in CSV format")
.with_parameter(help_text("--anonymize", "Anonymize the row contents").optional())
.with_parameter(help_text("path", "The path to the file to write"))
.with_tags({"io", "scripting", "sql"})
.with_example({"To write SQL results as CSV to /tmp/table.csv",
@ -5181,6 +5215,7 @@ readline_context::command_t STD_COMMANDS[] = {
help_text(":write-json-to")
.with_summary("Write SQL results to the given file in JSON format")
.with_parameter(help_text("--anonymize", "Anonymize the JSON values").optional())
.with_parameter(help_text("path", "The path to the file to write"))
.with_tags({"io", "scripting", "sql"})
.with_example({"To write SQL results as JSON to /tmp/table.json",
@ -5191,6 +5226,7 @@ readline_context::command_t STD_COMMANDS[] = {
help_text(":write-jsonlines-to")
.with_summary(
"Write SQL results to the given file in JSON Lines format")
.with_parameter(help_text("--anonymize", "Anonymize the JSON values").optional())
.with_parameter(help_text("path", "The path to the file to write"))
.with_tags({"io", "scripting", "sql"})
.with_example({"To write SQL results as JSON Lines to /tmp/table.json",
@ -5201,6 +5237,7 @@ readline_context::command_t STD_COMMANDS[] = {
help_text(":write-table-to")
.with_summary(
"Write SQL results to the given file in a tabular format")
.with_parameter(help_text("--anonymize", "Anonymize the table contents").optional())
.with_parameter(help_text("path", "The path to the file to write"))
.with_tags({"io", "scripting", "sql"})
.with_example({"To write SQL results as text to /tmp/table.txt",
@ -5216,6 +5253,7 @@ readline_context::command_t STD_COMMANDS[] = {
.with_parameter(help_text("--view={log,db}",
"The view to use as the source of data")
.optional())
.with_parameter(help_text("--anonymize", "Anonymize the lines").optional())
.with_parameter(help_text("path", "The path to the file to write"))
.with_tags({"io", "scripting", "sql"})
.with_example(
@ -5227,6 +5265,7 @@ readline_context::command_t STD_COMMANDS[] = {
help_text(":write-view-to")
.with_summary("Write the text in the top view to the given file "
"without any formatting")
.with_parameter(help_text("--anonymize", "Anonymize the lines").optional())
.with_parameter(help_text("path", "The path to the file to write"))
.with_tags({"io", "scripting", "sql"})
.with_example(
@ -5237,6 +5276,7 @@ readline_context::command_t STD_COMMANDS[] = {
help_text(":write-screen-to")
.with_summary("Write the displayed text or SQL results to the given "
"file without any formatting")
.with_parameter(help_text("--anonymize", "Anonymize the lines").optional())
.with_parameter(help_text("path", "The path to the file to write"))
.with_tags({"io", "scripting", "sql"})
.with_example({"To write only the displayed text to /tmp/table.txt",

@ -104,6 +104,13 @@ public:
return *this;
}
array_t to_array() {
array_t retval;
this->h_context.Final(retval.out(0), retval.out(0));
return retval;
}
void to_string(auto_buffer& buf)
{
array_t bits;
@ -120,6 +127,14 @@ public:
return bits.to_string();
}
std::string to_uuid_string()
{
array_t bits;
this->h_context.Final(bits.out(0), bits.out(1));
return bits.to_uuid_string();
}
private:
SpookyHash h_context;
};

@ -402,9 +402,10 @@ matcher::matches(uint32_t options)
{
this->mb_input.i_next_offset = -1;
} else if (this->mb_match_data[0]->empty()) {
this->mb_input.i_next_offset = this->mb_match_data[0]->sf_end + 1;
this->mb_input.i_next_offset
= this->mb_match_data.md_ovector[1] + 1;
} else {
this->mb_input.i_next_offset = this->mb_match_data[0]->sf_end;
this->mb_input.i_next_offset = this->mb_match_data.md_ovector[1];
}
this->mb_match_data.md_input.i_next_offset
= this->mb_input.i_next_offset;

@ -82,7 +82,7 @@ public:
return string_fragment::from_byte_range(
this->md_input.i_string.sf_string,
this->md_input.i_next_offset,
this->md_input.i_string.sf_begin + this->md_input.i_next_offset,
this->md_input.i_string.sf_end);
}

@ -34,6 +34,7 @@
#include "scn/scn.h"
#include "spookyhash/SpookyV2.h"
#include "sqlite-extension-func.hh"
#include "text_anonymizer.hh"
#include "vtab_module.hh"
#include "vtab_module_json.hh"
#include "yajl/api/yajl_gen.h"
@ -617,6 +618,14 @@ sql_humanize_file_size(file_ssize_t value)
return humanize::file_size(value, humanize::alignment::columnar);
}
std::string
sql_anonymize(string_fragment frag)
{
static safe::Safe<lnav::text_anonymizer> ta;
return ta.writeAccess()->next(frag);
}
int
string_extension_functions(struct FuncDef** basic_funcs,
struct FuncDefAgg** agg_funcs)
@ -729,6 +738,17 @@ string_extension_functions(struct FuncDef** basic_funcs,
"4, 5, 6, 7, 8]')",
})),
sqlite_func_adapter<decltype(&sql_anonymize), sql_anonymize>::builder(
help_text("anonymize",
"Replace identifying information with random values.")
.sql_function()
.with_parameter({"value", "The text to anonymize"})
.with_tags({"string"})
.with_example({
"To anonymize an IP address",
"SELECT anonymize('Hello, 192.168.1.2')",
})),
sqlite_func_adapter<decltype(&extract), extract>::builder(
help_text("extract",
"Automatically Parse and extract data from a string")

@ -58,10 +58,6 @@ libtailerservice_a_CPPFLAGS = \
-I$(srcdir)/../third-party \
-I$(top_srcdir)/src/third-party/scnlib/include
libtailerservice_a_LIBADD = \
libtailercommon.a \
libtailerpp.a
libtailerservice_a_SOURCES = \
tailerbin.cc \
tailer.looper.cc

@ -0,0 +1,514 @@
/**
* Copyright (c) 2022, Timothy Stack
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Timothy Stack nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "text_anonymizer.hh"
#include <arpa/inet.h>
#include <curl/curl.h>
#include "animals-json.h"
#include "config.h"
#include "data_scanner.hh"
#include "diseases-json.h"
#include "ghc/filesystem.hpp"
#include "lnav_util.hh"
#include "pcrepp/pcre2pp.hh"
#include "words-json.h"
#include "yajlpp/yajlpp_def.hh"
namespace lnav {
struct random_list {
std::vector<std::string> rl_data;
std::string at_index(size_t index) const
{
auto counter = index / this->rl_data.size();
auto mod = index % this->rl_data.size();
auto retval = this->rl_data[mod];
if (counter > 0) {
retval = fmt::format(FMT_STRING("{}{}"), retval, counter);
}
return retval;
}
};
static const typed_json_path_container<random_list> random_list_handlers = {
yajlpp::property_handler("data#").for_field(&random_list::rl_data),
};
static random_list
load_word_list()
{
static const intern_string_t name
= intern_string::lookup(words_json.get_name());
auto parse_res
= random_list_handlers.parser_for(name).with_ignore_unused(false).of(
words_json.to_string_fragment());
return parse_res.unwrap();
}
static const random_list&
get_word_list()
{
static const auto retval = load_word_list();
return retval;
}
static random_list
load_animal_list()
{
static const intern_string_t name
= intern_string::lookup(animals_json.get_name());
auto parse_res
= random_list_handlers.parser_for(name).with_ignore_unused(false).of(
animals_json.to_string_fragment());
return parse_res.unwrap();
}
static const random_list&
get_animal_list()
{
static const auto retval = load_animal_list();
return retval;
}
static random_list
load_disease_list()
{
static const intern_string_t name
= intern_string::lookup(diseases_json.get_name());
auto parse_res
= random_list_handlers.parser_for(name).with_ignore_unused(false).of(
diseases_json.to_string_fragment());
return parse_res.unwrap();
}
static const random_list&
get_disease_list()
{
static const auto retval = load_disease_list();
return retval;
}
std::string
text_anonymizer::next(string_fragment line)
{
data_scanner ds(line);
std::string retval;
while (true) {
auto tok_res = ds.tokenize2();
if (!tok_res) {
break;
}
switch (tok_res->tr_token) {
case DT_URL: {
auto url_str = tok_res->to_string();
auto* cu = curl_url();
if (curl_url_set(cu, CURLUPART_URL, url_str.c_str(), 0)
!= CURLUE_OK)
{
retval += "<unparseable-url>";
} else {
auto_mem<char> url_part(curl_free);
if (curl_url_get(
cu, CURLUPART_USER, url_part.out(), CURLU_URLDECODE)
== CURLUE_OK)
{
auto anon_user = this->get_default(
this->ta_user_names,
url_part.in(),
[](size_t size, auto& user) {
return get_animal_list().at_index(size);
});
curl_url_set(cu,
CURLUPART_USER,
anon_user.c_str(),
CURLU_URLENCODE);
}
if (curl_url_get(cu,
CURLUPART_PASSWORD,
url_part.out(),
CURLU_URLDECODE)
== CURLUE_OK)
{
auto anon_pass
= hasher()
.update(url_part.in(), strlen(url_part.in()))
.to_string();
curl_url_set(cu,
CURLUPART_PASSWORD,
anon_pass.c_str(),
CURLU_URLENCODE);
}
if (curl_url_get(
cu, CURLUPART_HOST, url_part.out(), CURLU_URLDECODE)
== CURLUE_OK)
{
auto anon_host = this->get_default(
this->ta_host_names,
url_part.in(),
[](size_t size, auto& hn) {
const auto& diseases = get_disease_list();
return fmt::format(FMT_STRING("{}.example.com"),
diseases.at_index(size));
});
curl_url_set(cu,
CURLUPART_HOST,
anon_host.c_str(),
CURLU_URLENCODE);
}
if (curl_url_get(
cu, CURLUPART_PATH, url_part.out(), CURLU_URLDECODE)
== CURLUE_OK)
{
ghc::filesystem::path url_path(url_part.in());
ghc::filesystem::path anon_path;
for (const auto& comp : url_path) {
if (comp == comp.root_path()) {
anon_path = anon_path / comp;
continue;
}
anon_path = anon_path / this->next(comp.string());
}
curl_url_set(cu,
CURLUPART_PATH,
anon_path.c_str(),
CURLU_URLENCODE);
}
if (curl_url_get(cu,
CURLUPART_QUERY,
url_part.out(),
CURLU_URLDECODE)
== CURLUE_OK)
{
static const auto SPLIT_RE
= lnav::pcre2pp::code::from_const(R"((&))");
curl_url_set(cu, CURLUPART_QUERY, nullptr, 0);
auto url_query
= string_fragment::from_c_str(url_part.in());
auto replacer = [this, cu](const std::string& comp) {
std::string anon_query;
auto eq_index = comp.find('=');
if (eq_index != std::string::npos) {
anon_query = fmt::format(
FMT_STRING("{}={}"),
this->next(comp.substr(0, eq_index)),
this->next(comp.substr(eq_index + 1)));
} else {
anon_query = this->next(comp);
}
curl_url_set(cu,
CURLUPART_QUERY,
anon_query.c_str(),
CURLU_URLENCODE | CURLU_APPENDQUERY);
};
auto loop_res
= SPLIT_RE.capture_from(url_query).for_each(
[&replacer](lnav::pcre2pp::match_data& md) {
replacer(md.leading().to_string());
});
if (loop_res.isOk()) {
replacer(loop_res.unwrap().to_string());
}
}
if (curl_url_get(cu,
CURLUPART_FRAGMENT,
url_part.out(),
CURLU_URLDECODE)
== CURLUE_OK)
{
auto anon_frag = this->next(
string_fragment::from_c_str(url_part.in()));
curl_url_set(cu,
CURLUPART_FRAGMENT,
anon_frag.c_str(),
CURLU_URLENCODE);
}
auto_mem<char> anon_url(curl_free);
if (curl_url_get(cu, CURLUPART_URL, anon_url.out(), 0)
== CURLUE_OK)
{
retval.append(anon_url.in());
}
}
break;
}
case DT_PATH: {
ghc::filesystem::path inp_path(tok_res->to_string());
ghc::filesystem::path anon_path;
for (const auto& comp : inp_path) {
auto comp_str = comp.string();
if (comp == comp.root_path() || comp == inp_path) {
anon_path = anon_path / comp;
continue;
}
anon_path = anon_path / this->next(comp_str);
}
retval += anon_path.string();
break;
}
case DT_CREDIT_CARD_NUMBER: {
auto cc = tok_res->to_string();
auto has_spaces = cc.size() > 16;
auto new_end = std::remove_if(
cc.begin(), cc.end(), [](auto ch) { return ch == ' '; });
cc.erase(new_end, cc.end());
auto anon_cc = hasher().update(cc).to_string().substr(0, 16);
if (has_spaces) {
anon_cc.insert(12, " ");
anon_cc.insert(8, " ");
anon_cc.insert(4, " ");
}
retval += anon_cc;
break;
}
case DT_MAC_ADDRESS: {
// 00-00-5E-00-53-00
auto mac_addr = tok_res->to_string();
retval += this->get_default(
this->ta_mac_addresses,
mac_addr,
[](size_t size, auto& inp) {
uint32_t base_mac = 0x5e005300;
base_mac += size;
auto anon_mac = byte_array<6>::from({
0x00,
0x00,
(unsigned char) ((base_mac >> 24) & 0xff),
(unsigned char) ((base_mac >> 16) & 0xff),
(unsigned char) ((base_mac >> 8) & 0xff),
(unsigned char) ((base_mac >> 0) & 0xff),
});
return anon_mac.to_string(
nonstd::make_optional(inp[2]));
});
break;
}
case DT_HEX_DUMP: {
auto hex_str = tok_res->to_string();
auto hash_str = hasher().update(hex_str).to_array().to_string(
nonstd::make_optional(hex_str[2]));
std::string anon_hex;
while (anon_hex.size() < hex_str.size()) {
anon_hex += hash_str;
}
anon_hex.resize(hex_str.size());
retval += anon_hex;
break;
}
case DT_IPV4_ADDRESS: {
auto ipv4 = tok_res->to_string();
retval += this->get_default(
this->ta_ipv4_addresses, ipv4, [](size_t size, auto& _) {
char anon_ipv4[INET_ADDRSTRLEN];
struct in_addr ia;
inet_aton("10.0.0.0", &ia);
ia.s_addr = htonl(ntohl(ia.s_addr) + 1 + size);
inet_ntop(AF_INET, &ia, anon_ipv4, sizeof(anon_ipv4));
return std::string{anon_ipv4};
});
break;
}
case DT_IPV6_ADDRESS: {
auto ipv6 = tok_res->to_string();
retval += this->get_default(
this->ta_ipv6_addresses, ipv6, [](size_t size, auto& _) {
char anon_ipv6[INET6_ADDRSTRLEN];
struct in6_addr ia;
uint32_t* ia6_addr32 = (uint32_t*) &ia.s6_addr[12];
inet_pton(AF_INET6, "2001:db8::", &ia);
*ia6_addr32 = htonl(ntohl(*ia6_addr32) + 1 + size);
inet_ntop(AF_INET6, &ia, anon_ipv6, sizeof(anon_ipv6));
return std::string{anon_ipv6};
});
break;
}
case DT_EMAIL: {
auto email_addr = tok_res->to_string();
auto at_index = email_addr.find('@');
retval += fmt::format(
FMT_STRING("{}@{}.example.com"),
this->get_default(this->ta_user_names,
email_addr.substr(0, at_index),
[](auto size, const auto& inp) {
return get_animal_list().at_index(
size);
}),
this->get_default(this->ta_host_names,
email_addr.substr(at_index + 1),
[](auto size, const auto& inp) {
return get_disease_list().at_index(
size);
}));
break;
}
case DT_WORD:
case DT_SYMBOL: {
static const auto SPLIT_RE = lnav::pcre2pp::code::from_const(
R"((\.|::|_|-|/|\\|\d+))");
auto symbol_frag = ds.to_string_fragment(tok_res->tr_capture);
auto sym_provider = [](auto size, const auto& inp) {
if (inp.size() <= 4) {
return inp;
}
auto comp_frag = string_fragment::from_str(inp);
return string_fragment::from_str(
get_word_list().at_index(size))
.to_string_with_case_style(
comp_frag.detect_text_case_style());
};
auto cap_res
= SPLIT_RE.capture_from(symbol_frag)
.for_each([this, &retval, &sym_provider](
lnav::pcre2pp::match_data& md) {
auto comp = md.leading().to_string();
retval
+= this->get_default(
this->ta_symbols, comp, sym_provider)
+ md[0]->to_string();
});
if (cap_res.isErr()) {
retval += "<symbol>";
} else {
auto remaining = cap_res.unwrap().to_string();
retval += this->get_default(
this->ta_symbols, remaining, sym_provider);
}
break;
}
case DT_QUOTED_STRING: {
auto anon_inner = this->next(
ds.to_string_fragment(tok_res->tr_inner_capture)
.to_string());
retval += line.sub_range(tok_res->tr_capture.c_begin,
tok_res->tr_inner_capture.c_begin)
.to_string()
+ anon_inner
+ ds.to_string_fragment(tok_res->tr_capture).back();
break;
}
case DT_XML_OPEN_TAG: {
auto open_tag = tok_res->to_string();
auto space_index = open_tag.find(' ');
if (space_index == std::string::npos) {
retval += open_tag;
} else {
static const auto ATTR_RE
= lnav::pcre2pp::code::from_const(R"([\w\-]+=)");
auto remaining = string_fragment::from_str_range(
open_tag, space_index, open_tag.size());
auto md = ATTR_RE.create_match_data();
retval += open_tag.substr(0, space_index + 1);
while (!remaining.empty()) {
auto cap_res = ATTR_RE.capture_from(remaining)
.into(md)
.matches()
.ignore_error();
if (!cap_res) {
break;
}
retval += md.leading();
retval += md[0]->to_string();
remaining = md.remaining();
data_scanner ds(remaining);
auto attr_tok_res = ds.tokenize2();
if (!attr_tok_res) {
continue;
}
retval += this->next(attr_tok_res->to_string());
remaining = remaining.substr(
attr_tok_res->tr_capture.length());
}
retval += remaining.to_string();
}
break;
}
case DT_UUID: {
retval
+= hasher().update(tok_res->to_string()).to_uuid_string();
break;
}
default: {
retval += tok_res->to_string();
break;
}
}
}
return retval;
}
} // namespace lnav

@ -0,0 +1,75 @@
/**
* Copyright (c) 2022, Timothy Stack
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Timothy Stack nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef lnav_text_anonymizer_hh
#define lnav_text_anonymizer_hh
#include <string>
#include <vector>
#include "base/intern_string.hh"
#include "robin_hood/robin_hood.h"
namespace lnav {
class text_anonymizer {
public:
text_anonymizer() = default;
std::string next(string_fragment line);
private:
template<typename F>
const std::string& get_default(
robin_hood::unordered_map<std::string, std::string>& mapping,
const std::string& input,
F provider)
{
auto iter = mapping.find(input);
if (iter == mapping.end()) {
auto emp_res = mapping.template emplace(
input, provider(mapping.size(), input));
iter = emp_res.first;
}
return iter->second;
}
robin_hood::unordered_map<std::string, std::string> ta_mac_addresses;
robin_hood::unordered_map<std::string, std::string> ta_ipv4_addresses;
robin_hood::unordered_map<std::string, std::string> ta_ipv6_addresses;
robin_hood::unordered_map<std::string, std::string> ta_user_names;
robin_hood::unordered_map<std::string, std::string> ta_host_names;
robin_hood::unordered_map<std::string, std::string> ta_symbols;
};
} // namespace lnav
#endif

File diff suppressed because one or more lines are too long

@ -573,16 +573,19 @@ struct json_path_handler : public json_path_handler_base {
template<typename T, typename... Args>
struct LastIsVector {
using value_type = typename LastIsVector<Args...>::value_type;
static constexpr bool value = LastIsVector<Args...>::value;
};
template<typename T, typename U>
struct LastIsVector<std::vector<U> T::*> {
using value_type = U;
static constexpr bool value = true;
};
template<typename T, typename U>
struct LastIsVector<U T::*> {
using value_type = void;
static constexpr bool value = false;
};
@ -641,8 +644,41 @@ struct json_path_handler : public json_path_handler_base {
return *this;
}
template<
typename... Args,
std::enable_if_t<LastIs<std::vector<std::string>, Args...>::value, bool>
= true>
json_path_handler& for_field(Args... args)
{
this->add_cb(str_field_cb2);
this->jph_str_cb = [args...](yajlpp_parse_context* ypc,
const unsigned char* str,
size_t len) {
auto obj = ypc->ypc_obj_stack.top();
auto value_str = std::string((const char*) str, len);
auto jph = ypc->ypc_current_handler;
if (jph->jph_pattern) {
if (!jph->jph_pattern->find_in(value_str).ignore_error()) {
jph->report_pattern_error(ypc, value_str);
}
}
json_path_handler::get_field(obj, args...)
.emplace_back(std::move(value_str));
return 1;
};
return *this;
}
template<typename... Args,
std::enable_if_t<LastIsVector<Args...>::value, bool> = true>
std::enable_if_t<LastIsVector<Args...>::value, bool> = true,
std::enable_if_t<
!std::is_same<typename LastIsVector<Args...>::value_type,
std::string>::value,
bool>
= true>
json_path_handler& for_field(Args... args)
{
this->jph_obj_provider

@ -64,6 +64,11 @@ add_executable(test_top_status test_top_status.cc test_stubs.cc)
target_link_libraries(test_top_status diag logfmt)
add_test(NAME test_top_status COMMAND test_top_status)
add_executable(test_text_anonymizer test_text_anonymizer.cc test_stubs.cc)
target_include_directories(test_text_anonymizer PUBLIC ../src/third-party/doctest-root)
target_link_libraries(test_text_anonymizer diag)
add_test(NAME test_text_anonymizer COMMAND test_text_anonymizer)
add_executable(drive_view_colors drive_view_colors.cc test_stubs.cc)
target_link_libraries(drive_view_colors diag)

@ -76,6 +76,7 @@ check_PROGRAMS = \
test_log_accel \
test_ncurses_unicode \
test_reltime \
test_text_anonymizer \
test_top_status
AM_LDFLAGS = \
@ -136,6 +137,8 @@ test_line_buffer2_SOURCES = test_line_buffer2.cc
test_log_accel_SOURCES = test_log_accel.cc
test_text_anonymizer_SOURCES = test_text_anonymizer.cc
test_top_status_SOURCES = test_top_status.cc
test_abbrev_SOURCES = test_abbrev.cc
@ -416,6 +419,7 @@ TESTS = \
test_sql_views_vtab.sh \
test_sql_xml_func.sh \
test_sql_yaml_func.sh \
test_text_anonymizer \
test_text_file.sh \
test_tui.sh \
test_data_parser.sh \

@ -0,0 +1,88 @@
2022-06-02T12:26:22.072Z info vpxd[47413] [Originator@6876 sub=vpxLro opID=21fa61e9-3e] [VpxLRO] -- BEGIN lro-954041 -- AuthorizationManager -- vim.AuthorizationManager.hasUserPrivilegeOnEntities -- 52768da7-4006-3d4a-4917-ee027373630f(522e0475-8901-e8b8-1eb8-07ec729ac50c)
key 23:23 ^
sym 23:24 ^ Z
pair 23:24 ^ Z
key 30:30 ^
sym 30:34 ^--^ vpxd
pair 30:34 ^--^ vpxd
key 35:35 ^
num 35:40 ^---^ 47413
val 35:40 ^---^ 47413
grp 35:40 ^---^ 47413
pair 35:40 ^---^ 47413
key 43:43 ^
key 43:62 ^-----------------^ Originator@6876 sub
sym 63:69 ^----^ vpxLro
val 63:69 ^----^ vpxLro
pair 43:69 ^------------------------^ Originator@6876 sub=vpxLro
key 70:74 ^--^ opID
sym 75:86 ^---------^ 21fa61e9-3e
val 75:86 ^---------^ 21fa61e9-3e
pair 70:86 ^--------------^ opID=21fa61e9-3e
grp 43:86 ^-----------------------------------------^ Originator@6876 sub=vpxLro opID=21fa61e9-3e
pair 43:86 ^-----------------------------------------^ Originator@6876 sub=vpxLro opID=21fa61e9-3e
key 89:89 ^
sym 89:95 ^----^ VpxLRO
val 89:95 ^----^ VpxLRO
grp 89:95 ^----^ VpxLRO
pair 89:95 ^----^ VpxLRO
key 97:97 ^
sym 97:99 ^^ --
pair 97:99 ^^ --
key 100:100 ^
sym 100:105 ^---^ BEGIN
pair 100:105 ^---^ BEGIN
key 106:106 ^
sym 106:116 ^--------^ lro-954041
pair 106:116 ^--------^ lro-954041
key 117:117 ^
sym 117:119 ^^ --
pair 117:119 ^^ --
key 120:120 ^
sym 120:140 ^------------------^ AuthorizationManager
pair 120:140 ^------------------^ AuthorizationManager
key 141:141 ^
sym 141:143 ^^ --
pair 141:143 ^^ --
key 144:144 ^
sym 144:195 ^-------------------------------------------------^ vim.AuthorizationManager.hasUserPrivilegeOnEntities
pair 144:195 ^-------------------------------------------------^ vim.AuthorizationManager.hasUserPrivilegeOnEntities
key 196:196 ^
sym 196:198 ^^ --
pair 196:198 ^^ --
key 199:199 ^
uuid 199:235 ^----------------------------------^ 52768da7-4006-3d4a-4917-ee027373630f
pair 199:235 ^----------------------------------^ 52768da7-4006-3d4a-4917-ee027373630f
key 236:236 ^
uuid 236:272 ^----------------------------------^ 522e0475-8901-e8b8-1eb8-07ec729ac50c
val 236:272 ^----------------------------------^ 522e0475-8901-e8b8-1eb8-07ec729ac50c
grp 236:272 ^----------------------------------^ 522e0475-8901-e8b8-1eb8-07ec729ac50c
pair 236:272 ^----------------------------------^ 522e0475-8901-e8b8-1eb8-07ec729ac50c
msg :2022-06-02T12:26:22.072Z info vpxd[47413] [Originator@6876 sub=vpxLro opID=21fa61e9-3e] [VpxLRO] -- BEGIN lro-954041 -- AuthorizationManager -- vim.AuthorizationManager.hasUserPrivilegeOnEntities -- 52768da7-4006-3d4a-4917-ee027373630f(522e0475-8901-e8b8-1eb8-07ec729ac50c)
format :2022-06-02T12:26:22.072# info #[#] [#] [#] # # # # # # # # #(#)
{
"col_0": "Z",
"col_1": "vpxd",
"col_2": [
47413
],
"col_3": {
"Originator@6876 sub": "vpxLro",
"opID": "21fa61e9-3e"
},
"col_4": [
"VpxLRO"
],
"col_5": "--",
"col_6": "BEGIN",
"col_7": "lro-954041",
"col_8": "--",
"col_9": "AuthorizationManager",
"col_10": "--",
"col_11": "vim.AuthorizationManager.hasUserPrivilegeOnEntities",
"col_12": "--",
"col_13": "52768da7-4006-3d4a-4917-ee027373630f",
"col_14": [
"522e0475-8901-e8b8-1eb8-07ec729ac50c"
]
}

@ -56,6 +56,7 @@ main(int argc, char* argv[])
{
int c, retval = EXIT_SUCCESS;
bool prompt = false, is_log = false, pretty_print = false;
bool scanner_details = false;
{
static auto builtin_formats
@ -75,7 +76,7 @@ main(int argc, char* argv[])
load_formats(paths, errors);
}
while ((c = getopt(argc, argv, "pPl")) != -1) {
while ((c = getopt(argc, argv, "pPls")) != -1) {
switch (c) {
case 'p':
prompt = true;
@ -89,6 +90,10 @@ main(int argc, char* argv[])
is_log = true;
break;
case 's':
scanner_details = true;
break;
default:
retval = EXIT_FAILURE;
break;
@ -191,6 +196,52 @@ main(int argc, char* argv[])
data_parser::TRACE_FILE = fopen("scanned.dpt", "w");
data_scanner ds(sub_line, body.lr_start);
if (scanner_details) {
fprintf(out,
" %s\n",
ds.get_input().to_string().c_str());
while (true) {
auto tok_res = ds.tokenize2();
if (!tok_res) {
break;
}
fprintf(out,
"%4s %3d:%-3d ",
data_scanner::token2name(tok_res->tr_token),
tok_res->tr_capture.c_begin,
tok_res->tr_capture.c_end);
size_t cap_index = 0;
for (; cap_index < tok_res->tr_capture.c_end;
cap_index++)
{
if (cap_index == tok_res->tr_capture.c_begin) {
fputc('^', out);
} else if (cap_index
== (tok_res->tr_capture.c_end - 1))
{
fputc('^', out);
} else if (cap_index > tok_res->tr_capture.c_begin)
{
fputc('-', out);
} else {
fputc(' ', out);
}
}
for (; cap_index < (int) ds.get_input().length();
cap_index++)
{
fputc(' ', out);
}
auto sub = tok_res->to_string();
fprintf(out, " %s\n", sub.c_str());
}
}
ds.reset();
data_parser dp(&ds);
std::string msg_format;

@ -112,9 +112,7 @@ int
main(int argc, char* argv[])
{
int retval = EXIT_SUCCESS;
const char* errptr;
auto_fd fd;
int eoff;
if (argc < 3) {
fprintf(stderr, "error: expecting pattern and file arguments\n");

@ -54,6 +54,8 @@ EXPECTED_FILES = \
$(srcdir)/%reldir%/test_cmds.sh_2de9ec294e2f533d13e04c70d9525f8b58d47bb2.out \
$(srcdir)/%reldir%/test_cmds.sh_2e123104cdd2087ac40731a0aa533ba6a87ea744.err \
$(srcdir)/%reldir%/test_cmds.sh_2e123104cdd2087ac40731a0aa533ba6a87ea744.out \
$(srcdir)/%reldir%/test_cmds.sh_2e67bdbbc9a14aa772b2a9f755ed8f8124708558.err \
$(srcdir)/%reldir%/test_cmds.sh_2e67bdbbc9a14aa772b2a9f755ed8f8124708558.out \
$(srcdir)/%reldir%/test_cmds.sh_2ff0fe712c9b0012e42282c5f77b0b83cad37ddf.err \
$(srcdir)/%reldir%/test_cmds.sh_2ff0fe712c9b0012e42282c5f77b0b83cad37ddf.out \
$(srcdir)/%reldir%/test_cmds.sh_305b1dfdfe785b945df4220aad6671ae1d364f55.err \
@ -192,6 +194,8 @@ EXPECTED_FILES = \
$(srcdir)/%reldir%/test_cmds.sh_dbdd62995fdefc8318053af05a32416eccfa79fc.out \
$(srcdir)/%reldir%/test_cmds.sh_dd41fbbcd71699314af232156d4155fbdf849131.err \
$(srcdir)/%reldir%/test_cmds.sh_dd41fbbcd71699314af232156d4155fbdf849131.out \
$(srcdir)/%reldir%/test_cmds.sh_df6f4cea16bb8f20e6408fe4b40335e6de8a7f18.err \
$(srcdir)/%reldir%/test_cmds.sh_df6f4cea16bb8f20e6408fe4b40335e6de8a7f18.out \
$(srcdir)/%reldir%/test_cmds.sh_e495cf059477e3f80c3241c6f8d5808b6f1d19c7.err \
$(srcdir)/%reldir%/test_cmds.sh_e495cf059477e3f80c3241c6f8d5808b6f1d19c7.out \
$(srcdir)/%reldir%/test_cmds.sh_e7e8244fac65bc51dbd5af31be476fe3b8776bfc.err \
@ -210,8 +214,6 @@ EXPECTED_FILES = \
$(srcdir)/%reldir%/test_cmds.sh_ff6faebbde8586e04bfadba14a3d2bb4451784ad.out \
$(srcdir)/%reldir%/test_config.sh_2765ea0d4c037b8c935840604edb0ae796c97a04.err \
$(srcdir)/%reldir%/test_config.sh_2765ea0d4c037b8c935840604edb0ae796c97a04.out \
$(srcdir)/%reldir%/test_config.sh_5105c29004e297521310ca0bd0fd560b01c2c549.err \
$(srcdir)/%reldir%/test_config.sh_5105c29004e297521310ca0bd0fd560b01c2c549.out \
$(srcdir)/%reldir%/test_config.sh_5fd9fbccc35e9b06abdd913da0c16bdb306b926e.err \
$(srcdir)/%reldir%/test_config.sh_5fd9fbccc35e9b06abdd913da0c16bdb306b926e.out \
$(srcdir)/%reldir%/test_config.sh_a0907769aba112d628e7ebe39c4ec252e5e0bc69.err \
@ -240,12 +242,8 @@ EXPECTED_FILES = \
$(srcdir)/%reldir%/test_events.sh_ed8dc44add223341c03ccb7b3e18371bdb42b710.out \
$(srcdir)/%reldir%/test_format_loader.sh_15e861d2327512a721fd42ae51dc5427689e0bb6.err \
$(srcdir)/%reldir%/test_format_loader.sh_15e861d2327512a721fd42ae51dc5427689e0bb6.out \
$(srcdir)/%reldir%/test_format_loader.sh_3f1d6f35e8a9ae4fd3e91ffaa82a037b5a847ab7.err \
$(srcdir)/%reldir%/test_format_loader.sh_3f1d6f35e8a9ae4fd3e91ffaa82a037b5a847ab7.out \
$(srcdir)/%reldir%/test_format_loader.sh_5992e2695b7e6cf1f3520dbb87af8fc2b8f27088.err \
$(srcdir)/%reldir%/test_format_loader.sh_5992e2695b7e6cf1f3520dbb87af8fc2b8f27088.out \
$(srcdir)/%reldir%/test_format_loader.sh_a47f2b090a5d8a226783835c7ff7d1c8821f11ed.err \
$(srcdir)/%reldir%/test_format_loader.sh_a47f2b090a5d8a226783835c7ff7d1c8821f11ed.out \
$(srcdir)/%reldir%/test_format_loader.sh_fca6c1fb9f3aaa69b3ffb2d1a8a86434b2f4a247.err \
$(srcdir)/%reldir%/test_format_loader.sh_fca6c1fb9f3aaa69b3ffb2d1a8a86434b2f4a247.out \
$(srcdir)/%reldir%/test_json_format.sh_168cac40c27f547044c89d39eb0ff2ef81da4b21.err \
@ -744,6 +742,8 @@ EXPECTED_FILES = \
$(srcdir)/%reldir%/test_sql_str_func.sh_04712488fe50554eb36d3ced80f9a033602f3daa.out \
$(srcdir)/%reldir%/test_sql_str_func.sh_11bcc5d32eabbedb6974f160dace9ef1ef0009e9.err \
$(srcdir)/%reldir%/test_sql_str_func.sh_11bcc5d32eabbedb6974f160dace9ef1ef0009e9.out \
$(srcdir)/%reldir%/test_sql_str_func.sh_11d458fdadd00df1239a0eeaac049abb49ed212d.err \
$(srcdir)/%reldir%/test_sql_str_func.sh_11d458fdadd00df1239a0eeaac049abb49ed212d.out \
$(srcdir)/%reldir%/test_sql_str_func.sh_129e58679e72f3cc5864812026e49a7917baf3d0.err \
$(srcdir)/%reldir%/test_sql_str_func.sh_129e58679e72f3cc5864812026e49a7917baf3d0.out \
$(srcdir)/%reldir%/test_sql_str_func.sh_151a0fd71ef6837c8cbd8a67e315019b5812b079.err \

@ -1,6 +1,6 @@
✘ error: expecting file name or '-' to write to the terminal
 --> command-option:1
 | :write-to 
 = help: :write-to path
 = help: :write-to [--anonymize] path
══════════════════════════════════════════════════════════════════════
Overwrite the given file with any marked lines in the current view

@ -0,0 +1,23 @@
Apr 7 00:49:42 Tim-Abaft-iMac abashed[0]: Aberrant [abhorrent5701Aberrant]: Link up on en0, 1-Aboard, Full-abortive, Abounding flow-abrupt, Absent [796d,2301,0de1,0300,cde1,3800]
Apr 7 05:49:53 Tim-Abaft-iMac.absorbing Abstracted[17212]: -[absurd abundant] absurd abusive accept: <acceptable:0x511f30
accessible=<KSOmahaServer:0x510d80>
url="https://achondroplasia.example.com/account/accurate2"
achiever=0
acid=1
acidic=1
acoustic=1
body=
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<o:gupdate xmlns:o="http://acinetobacter-infections.example.com/accurate2/acrid" protocol="2.0" version="Act-1.2.0.7709" ismachine="1" requestid="{1ca0a968-cbe9-e75b-d00b-4859609878ea}">
<o:os platform="mac" version="activity" sp="10.10.2_x86_64h"></o:os>
<o:app appid="com.actually.Ad hoc" version="1.2.0.7709" lang="en-us" installage="180" brand="GGLG">
<o:ping r="1" a="1"></o:ping>
<o:updatecheck></o:updatecheck>
</o:app>
</o:gupdate>
>
Apr 7 07:31:56 Tim-Abaft-iMac.absorbing Add[36403]: ADDICTED: The Adhesive adjoining adjustment is admit 10.9.2 adorable of 10.10.2. Use advice's afford afraid to get afterthought aggressive agonizing agree
Call agreement:
Apr 7 07:31:56 Tim-Abaft-iMac.absorbing Add[36403]: 0 Ahead 0x00007fff8a9b3d9b ___Adhesive_Air_airplane_airport + 113
Apr 7 07:31:56 Tim-Abaft-iMac.absorbing Add[36403]: 1 ajar.alarm 0x00007fff8bc84c13 _alcoholic_alert_alike + 8
Apr 7 07:32:56 Tim-Abaft-iMac.absorbing alive[234]: Bad data { abc, 123, 456 )}]

@ -1,6 +1,6 @@
✘ error: write-json-to -- unavailable in secure mode
 --> command-option:2
 | :write-json-to /tmp/bad 
 = help: :write-json-to path
 = help: :write-json-to [--anonymize] path
══════════════════════════════════════════════════════════════════════
Write SQL results to the given file in JSON format

@ -1565,11 +1565,12 @@ For support questions, email:
:write-table-to path
:write-table-to [--anonymize] path
══════════════════════════════════════════════════════════════════════
Write SQL results to the given file in a tabular format
Parameter
path The path to the file to write
Parameters
--anonymize Anonymize the table contents
path The path to the file to write
See Also
:alt-msg, :append-to, :create-logline-table, :create-search-table,
:echo, :echo, :eval, :export-session-to, :export-session-to,
@ -1586,11 +1587,12 @@ For support questions, email:
:write-csv-to path
:write-csv-to [--anonymize] path
══════════════════════════════════════════════════════════════════════
Write SQL results to the given file in CSV format
Parameter
path The path to the file to write
Parameters
--anonymize Anonymize the row contents
path The path to the file to write
See Also
:alt-msg, :append-to, :create-logline-table, :create-search-table,
:echo, :echo, :eval, :export-session-to, :export-session-to,
@ -1606,11 +1608,12 @@ For support questions, email:
:write-json-to path
:write-json-to [--anonymize] path
══════════════════════════════════════════════════════════════════════
Write SQL results to the given file in JSON format
Parameter
path The path to the file to write
Parameters
--anonymize Anonymize the JSON values
path The path to the file to write
See Also
:alt-msg, :append-to, :create-logline-table, :create-search-table,
:echo, :echo, :eval, :export-session-to, :export-session-to,
@ -1626,11 +1629,12 @@ For support questions, email:
:write-jsonlines-to path
:write-jsonlines-to [--anonymize] path
══════════════════════════════════════════════════════════════════════
Write SQL results to the given file in JSON Lines format
Parameter
path The path to the file to write
Parameters
--anonymize Anonymize the JSON values
path The path to the file to write
See Also
:alt-msg, :append-to, :create-logline-table, :create-search-table,
:echo, :echo, :eval, :export-session-to, :export-session-to,
@ -1646,7 +1650,7 @@ For support questions, email:
:write-raw-to [--view={log,db}] path
:write-raw-to [--view={log,db}] [--anonymize] path
══════════════════════════════════════════════════════════════════════
In the log view, write the original log file content of the marked
messages to the file. In the DB view, the contents of the cells are
@ -1654,6 +1658,7 @@ For support questions, email:
Parameters
--view={log,db} The view to use as the source of
data
--anonymize Anonymize the lines
path The path to the file to write
See Also
:alt-msg, :append-to, :create-logline-table, :create-search-table,
@ -1671,12 +1676,13 @@ For support questions, email:
:write-screen-to path
:write-screen-to [--anonymize] path
══════════════════════════════════════════════════════════════════════
Write the displayed text or SQL results to the given file without
any formatting
Parameter
path The path to the file to write
Parameters
--anonymize Anonymize the lines
path The path to the file to write
See Also
:alt-msg, :append-to, :create-logline-table, :create-search-table,
:echo, :echo, :eval, :export-session-to, :export-session-to,
@ -1693,11 +1699,12 @@ For support questions, email:
:write-table-to path
:write-table-to [--anonymize] path
══════════════════════════════════════════════════════════════════════
Write SQL results to the given file in a tabular format
Parameter
path The path to the file to write
Parameters
--anonymize Anonymize the table contents
path The path to the file to write
See Also
:alt-msg, :append-to, :create-logline-table, :create-search-table,
:echo, :echo, :eval, :export-session-to, :export-session-to,
@ -1714,11 +1721,12 @@ For support questions, email:
:write-to path
:write-to [--anonymize] path
══════════════════════════════════════════════════════════════════════
Overwrite the given file with any marked lines in the current view
Parameter
path The path to the file to write
Parameters
--anonymize Anonymize the lines
path The path to the file to write
See Also
:alt-msg, :append-to, :echo, :echo, :eval, :export-session-to,
:export-session-to, :pipe-line-to, :pipe-to, :rebuild, :redirect-to,
@ -1733,12 +1741,13 @@ For support questions, email:
:write-view-to path
:write-view-to [--anonymize] path
══════════════════════════════════════════════════════════════════════
Write the text in the top view to the given file without any
formatting
Parameter
path The path to the file to write
Parameters
--anonymize Anonymize the lines
path The path to the file to write
See Also
:alt-msg, :append-to, :create-logline-table, :create-search-table,
:echo, :echo, :eval, :export-session-to, :export-session-to,
@ -1842,6 +1851,26 @@ For support questions, email:
anonymize(value)
══════════════════════════════════════════════════════════════════════
Replace identifying information with random values.
Parameter
value The text to anonymize
See Also
char(), charindex(), decode(), encode(), endswith(), extract(),
group_concat(), group_spooky_hash(), gunzip(), gzip(),
humanize_duration(), humanize_file_size(), instr(), leftstr(),
length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
printf(), proper(), regexp_capture(), regexp_capture_into_json(),
regexp_match(), regexp_replace(), replace(), replicate(), reverse(),
rightstr(), rtrim(), sparkline(), spooky_hash(), startswith(),
strfilter(), substr(), trim(), unicode(), upper(), xpath()
Example
#1 To anonymize an IP address:
;SELECT anonymize('Hello, 192.168.1.2') 
asin(num)
══════════════════════════════════════════════════════════════════════
Returns the arcsine of a number, in radians
@ -2018,14 +2047,14 @@ For support questions, email:
Parameter
X The unicode code point values
See Also
charindex(), decode(), encode(), endswith(), extract(), group_concat(),
group_spooky_hash(), gunzip(), gzip(), humanize_duration(),
humanize_file_size(), instr(), leftstr(), length(), logfmt2json(),
lower(), ltrim(), padc(), padl(), padr(), printf(), proper(),
regexp_capture(), regexp_capture_into_json(), regexp_match(),
regexp_replace(), replace(), replicate(), reverse(), rightstr(),
rtrim(), sparkline(), spooky_hash(), startswith(), strfilter(),
substr(), trim(), unicode(), upper(), xpath()
anonymize(), charindex(), decode(), encode(), endswith(), extract(),
group_concat(), group_spooky_hash(), gunzip(), gzip(),
humanize_duration(), humanize_file_size(), instr(), leftstr(),
length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
printf(), proper(), regexp_capture(), regexp_capture_into_json(),
regexp_match(), regexp_replace(), replace(), replicate(), reverse(),
rightstr(), rtrim(), sparkline(), spooky_hash(), startswith(),
strfilter(), substr(), trim(), unicode(), upper(), xpath()
Example
#1 To get a string with the code points 0x48 and 0x49:
;SELECT char(0x48, 0x49) 
@ -2043,14 +2072,14 @@ For support questions, email:
start The one-based index within the haystack to
start the search
See Also
char(), decode(), encode(), endswith(), extract(), group_concat(),
group_spooky_hash(), gunzip(), gzip(), humanize_duration(),
humanize_file_size(), instr(), leftstr(), length(), logfmt2json(),
lower(), ltrim(), padc(), padl(), padr(), printf(), proper(),
regexp_capture(), regexp_capture_into_json(), regexp_match(),
regexp_replace(), replace(), replicate(), reverse(), rightstr(),
rtrim(), sparkline(), spooky_hash(), startswith(), strfilter(),
substr(), trim(), unicode(), upper(), xpath()
anonymize(), char(), decode(), encode(), endswith(), extract(),
group_concat(), group_spooky_hash(), gunzip(), gzip(),
humanize_duration(), humanize_file_size(), instr(), leftstr(),
length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
printf(), proper(), regexp_capture(), regexp_capture_into_json(),
regexp_match(), regexp_replace(), replace(), replicate(), reverse(),
rightstr(), rtrim(), sparkline(), spooky_hash(), startswith(),
strfilter(), substr(), trim(), unicode(), upper(), xpath()
Examples
#1 To search for the string 'abc' within 'abcabc' and starting at position 2:
;SELECT charindex('abc', 'abcabc', 2) 
@ -2156,14 +2185,14 @@ For support questions, email:
algorithm One of the following encoding algorithms:
base64, hex, uri
See Also
char(), charindex(), encode(), endswith(), extract(), group_concat(),
group_spooky_hash(), gunzip(), gzip(), humanize_duration(),
humanize_file_size(), instr(), leftstr(), length(), logfmt2json(),
lower(), ltrim(), padc(), padl(), padr(), printf(), proper(),
regexp_capture(), regexp_capture_into_json(), regexp_match(),
regexp_replace(), replace(), replicate(), reverse(), rightstr(),
rtrim(), sparkline(), spooky_hash(), startswith(), strfilter(),
substr(), trim(), unicode(), upper(), xpath()
anonymize(), char(), charindex(), encode(), endswith(), extract(),
group_concat(), group_spooky_hash(), gunzip(), gzip(),
humanize_duration(), humanize_file_size(), instr(), leftstr(),
length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
printf(), proper(), regexp_capture(), regexp_capture_into_json(),
regexp_match(), regexp_replace(), replace(), replicate(), reverse(),
rightstr(), rtrim(), sparkline(), spooky_hash(), startswith(),
strfilter(), substr(), trim(), unicode(), upper(), xpath()
Example
#1 To decode the URI-encoded string '%63%75%72%6c':
;SELECT decode('%63%75%72%6c', 'uri') 
@ -2241,14 +2270,14 @@ For support questions, email:
algorithm One of the following encoding algorithms:
base64, hex, uri
See Also
char(), charindex(), decode(), endswith(), extract(), group_concat(),
group_spooky_hash(), gunzip(), gzip(), humanize_duration(),
humanize_file_size(), instr(), leftstr(), length(), logfmt2json(),
lower(), ltrim(), padc(), padl(), padr(), printf(), proper(),
regexp_capture(), regexp_capture_into_json(), regexp_match(),
regexp_replace(), replace(), replicate(), reverse(), rightstr(),
rtrim(), sparkline(), spooky_hash(), startswith(), strfilter(),
substr(), trim(), unicode(), upper(), xpath()
anonymize(), char(), charindex(), decode(), endswith(), extract(),
group_concat(), group_spooky_hash(), gunzip(), gzip(),
humanize_duration(), humanize_file_size(), instr(), leftstr(),
length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
printf(), proper(), regexp_capture(), regexp_capture_into_json(),
regexp_match(), regexp_replace(), replace(), replicate(), reverse(),
rightstr(), rtrim(), sparkline(), spooky_hash(), startswith(),
strfilter(), substr(), trim(), unicode(), upper(), xpath()
Examples
#1 To base64-encode 'Hello, World!':
;SELECT encode('Hello, World!', 'base64') 
@ -2270,14 +2299,14 @@ For support questions, email:
str The string to test
suffix The suffix to check in the string
See Also
char(), charindex(), decode(), encode(), extract(), group_concat(),
group_spooky_hash(), gunzip(), gzip(), humanize_duration(),
humanize_file_size(), instr(), leftstr(), length(), logfmt2json(),
lower(), ltrim(), padc(), padl(), padr(), printf(), proper(),
regexp_capture(), regexp_capture_into_json(), regexp_match(),
regexp_replace(), replace(), replicate(), reverse(), rightstr(),
rtrim(), sparkline(), spooky_hash(), startswith(), strfilter(),
substr(), trim(), unicode(), upper(), xpath()
anonymize(), char(), charindex(), decode(), encode(), extract(),
group_concat(), group_spooky_hash(), gunzip(), gzip(),
humanize_duration(), humanize_file_size(), instr(), leftstr(),
length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
printf(), proper(), regexp_capture(), regexp_capture_into_json(),
regexp_match(), regexp_replace(), replace(), replicate(), reverse(),
rightstr(), rtrim(), sparkline(), spooky_hash(), startswith(),
strfilter(), substr(), trim(), unicode(), upper(), xpath()
Examples
#1 To test if the string 'notbad.jpg' ends with '.jpg':
;SELECT endswith('notbad.jpg', '.jpg') 
@ -2310,14 +2339,14 @@ For support questions, email:
Parameter
str The string to parse
See Also
char(), charindex(), decode(), encode(), endswith(), group_concat(),
group_spooky_hash(), gunzip(), gzip(), humanize_duration(),
humanize_file_size(), instr(), leftstr(), length(), logfmt2json(),
lower(), ltrim(), padc(), padl(), padr(), printf(), proper(),
regexp_capture(), regexp_capture_into_json(), regexp_match(),
regexp_replace(), replace(), replicate(), reverse(), rightstr(),
rtrim(), sparkline(), spooky_hash(), startswith(), strfilter(),
substr(), trim(), unicode(), upper(), xpath()
anonymize(), char(), charindex(), decode(), encode(), endswith(),
group_concat(), group_spooky_hash(), gunzip(), gzip(),
humanize_duration(), humanize_file_size(), instr(), leftstr(),
length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
printf(), proper(), regexp_capture(), regexp_capture_into_json(),
regexp_match(), regexp_replace(), replace(), replicate(), reverse(),
rightstr(), rtrim(), sparkline(), spooky_hash(), startswith(),
strfilter(), substr(), trim(), unicode(), upper(), xpath()
Examples
#1 To extract key/value pairs from a string:
;SELECT extract('foo=1 bar=2 name="Rolo Tomassi"') 
@ -2425,8 +2454,8 @@ For support questions, email:
X The value to concatenate.
sep The separator to place between the values.
See Also
char(), charindex(), decode(), encode(), endswith(), extract(),
group_spooky_hash(), gunzip(), gzip(), humanize_duration(),
anonymize(), char(), charindex(), decode(), encode(), endswith(),
extract(), group_spooky_hash(), gunzip(), gzip(), humanize_duration(),
humanize_file_size(), instr(), leftstr(), length(), logfmt2json(),
lower(), ltrim(), padc(), padl(), padr(), printf(), proper(),
regexp_capture(), regexp_capture_into_json(), regexp_match(),
@ -2455,8 +2484,8 @@ For support questions, email:
Parameter
str The string to hash
See Also
char(), charindex(), decode(), encode(), endswith(), extract(),
group_concat(), gunzip(), gzip(), humanize_duration(),
anonymize(), char(), charindex(), decode(), encode(), endswith(),
extract(), group_concat(), gunzip(), gzip(), humanize_duration(),
humanize_file_size(), instr(), leftstr(), length(), logfmt2json(),
lower(), ltrim(), padc(), padl(), padr(), printf(), proper(),
regexp_capture(), regexp_capture_into_json(), regexp_match(),
@ -2475,14 +2504,14 @@ For support questions, email:
Parameter
b The blob to decompress
See Also
char(), charindex(), decode(), encode(), endswith(), extract(),
group_concat(), group_spooky_hash(), gzip(), humanize_duration(),
humanize_file_size(), instr(), leftstr(), length(), logfmt2json(),
lower(), ltrim(), padc(), padl(), padr(), printf(), proper(),
regexp_capture(), regexp_capture_into_json(), regexp_match(),
regexp_replace(), replace(), replicate(), reverse(), rightstr(),
rtrim(), sparkline(), spooky_hash(), startswith(), strfilter(),
substr(), trim(), unicode(), upper(), xpath()
anonymize(), char(), charindex(), decode(), encode(), endswith(),
extract(), group_concat(), group_spooky_hash(), gzip(),
humanize_duration(), humanize_file_size(), instr(), leftstr(),
length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
printf(), proper(), regexp_capture(), regexp_capture_into_json(),
regexp_match(), regexp_replace(), replace(), replicate(), reverse(),
rightstr(), rtrim(), sparkline(), spooky_hash(), startswith(),
strfilter(), substr(), trim(), unicode(), upper(), xpath()
gzip(value, ...)
══════════════════════════════════════════════════════════════════════
@ -2490,14 +2519,14 @@ For support questions, email:
Parameter
value The value to compress
See Also
char(), charindex(), decode(), encode(), endswith(), extract(),
group_concat(), group_spooky_hash(), gunzip(), humanize_duration(),
humanize_file_size(), instr(), leftstr(), length(), logfmt2json(),
lower(), ltrim(), padc(), padl(), padr(), printf(), proper(),
regexp_capture(), regexp_capture_into_json(), regexp_match(),
regexp_replace(), replace(), replicate(), reverse(), rightstr(),
rtrim(), sparkline(), spooky_hash(), startswith(), strfilter(),
substr(), trim(), unicode(), upper(), xpath()
anonymize(), char(), charindex(), decode(), encode(), endswith(),
extract(), group_concat(), group_spooky_hash(), gunzip(),
humanize_duration(), humanize_file_size(), instr(), leftstr(),
length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
printf(), proper(), regexp_capture(), regexp_capture_into_json(),
regexp_match(), regexp_replace(), replace(), replicate(), reverse(),
rightstr(), rtrim(), sparkline(), spooky_hash(), startswith(),
strfilter(), substr(), trim(), unicode(), upper(), xpath()
hex(X)
══════════════════════════════════════════════════════════════════════
@ -2518,15 +2547,15 @@ For support questions, email:
Parameter
secs The duration in seconds
See Also
char(), charindex(), date(), datetime(), decode(), encode(),
endswith(), extract(), group_concat(), group_spooky_hash(), gunzip(),
gzip(), humanize_file_size(), instr(), julianday(), leftstr(),
length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
printf(), proper(), regexp_capture(), regexp_capture_into_json(),
regexp_match(), regexp_replace(), replace(), replicate(), reverse(),
rightstr(), rtrim(), sparkline(), spooky_hash(), startswith(),
strfilter(), strftime(), substr(), time(), timediff(), timeslice(),
trim(), unicode(), upper(), xpath()
anonymize(), char(), charindex(), date(), datetime(), decode(),
encode(), endswith(), extract(), group_concat(), group_spooky_hash(),
gunzip(), gzip(), humanize_file_size(), instr(), julianday(),
leftstr(), length(), logfmt2json(), lower(), ltrim(), padc(), padl(),
padr(), printf(), proper(), regexp_capture(),
regexp_capture_into_json(), regexp_match(), regexp_replace(),
replace(), replicate(), reverse(), rightstr(), rtrim(), sparkline(),
spooky_hash(), startswith(), strfilter(), strftime(), substr(), time(),
timediff(), timeslice(), trim(), unicode(), upper(), xpath()
Examples
#1 To format a duration:
;SELECT humanize_duration(15 * 60) 
@ -2543,8 +2572,8 @@ For support questions, email:
Parameter
value The file size to format
See Also
char(), charindex(), decode(), encode(), endswith(), extract(),
group_concat(), group_spooky_hash(), gunzip(), gzip(),
anonymize(), char(), charindex(), decode(), encode(), endswith(),
extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
humanize_duration(), instr(), leftstr(), length(), logfmt2json(),
lower(), ltrim(), padc(), padl(), padr(), printf(), proper(),
regexp_capture(), regexp_capture_into_json(), regexp_match(),
@ -2580,8 +2609,8 @@ For support questions, email:
haystack The string to search within
needle The string to look for in the haystack
See Also
char(), charindex(), decode(), encode(), endswith(), extract(),
group_concat(), group_spooky_hash(), gunzip(), gzip(),
anonymize(), char(), charindex(), decode(), encode(), endswith(),
extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
humanize_duration(), humanize_file_size(), leftstr(), length(),
logfmt2json(), lower(), ltrim(), padc(), padl(), padr(), printf(),
proper(), regexp_capture(), regexp_capture_into_json(), regexp_match(),
@ -2805,8 +2834,8 @@ For support questions, email:
N The number of characters from the left side of the
string to return.
See Also
char(), charindex(), decode(), encode(), endswith(), extract(),
group_concat(), group_spooky_hash(), gunzip(), gzip(),
anonymize(), char(), charindex(), decode(), encode(), endswith(),
extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
humanize_duration(), humanize_file_size(), instr(), length(),
logfmt2json(), lower(), ltrim(), padc(), padl(), padr(), printf(),
proper(), regexp_capture(), regexp_capture_into_json(), regexp_match(),
@ -2830,8 +2859,8 @@ For support questions, email:
Parameter
str The string to determine the length of
See Also
char(), charindex(), decode(), encode(), endswith(), extract(),
group_concat(), group_spooky_hash(), gunzip(), gzip(),
anonymize(), char(), charindex(), decode(), encode(), endswith(),
extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
humanize_duration(), humanize_file_size(), instr(), leftstr(),
logfmt2json(), lower(), ltrim(), padc(), padl(), padr(), printf(),
proper(), regexp_capture(), regexp_capture_into_json(), regexp_match(),
@ -2950,8 +2979,8 @@ For support questions, email:
Parameter
str The logfmt message to parse
See Also
char(), charindex(), decode(), encode(), endswith(), extract(),
group_concat(), group_spooky_hash(), gunzip(), gzip(),
anonymize(), char(), charindex(), decode(), encode(), endswith(),
extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
humanize_duration(), humanize_file_size(), instr(), leftstr(),
length(), lower(), ltrim(), padc(), padl(), padr(), printf(), proper(),
regexp_capture(), regexp_capture_into_json(), regexp_match(),
@ -2971,8 +3000,8 @@ For support questions, email:
Parameter
str The string to convert.
See Also
char(), charindex(), decode(), encode(), endswith(), extract(),
group_concat(), group_spooky_hash(), gunzip(), gzip(),
anonymize(), char(), charindex(), decode(), encode(), endswith(),
extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
humanize_duration(), humanize_file_size(), instr(), leftstr(),
length(), logfmt2json(), ltrim(), padc(), padl(), padr(), printf(),
proper(), regexp_capture(), regexp_capture_into_json(), regexp_match(),
@ -2993,8 +3022,8 @@ For support questions, email:
str The string to trim characters from the left side
chars The characters to trim. Defaults to spaces.
See Also
char(), charindex(), decode(), encode(), endswith(), extract(),
group_concat(), group_spooky_hash(), gunzip(), gzip(),
anonymize(), char(), charindex(), decode(), encode(), endswith(),
extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
humanize_duration(), humanize_file_size(), instr(), leftstr(),
length(), logfmt2json(), lower(), padc(), padl(), padr(), printf(),
proper(), regexp_capture(), regexp_capture_into_json(), regexp_match(),
@ -3101,8 +3130,8 @@ For support questions, email:
str The string to pad
len The minimum desired length of the output string
See Also
char(), charindex(), decode(), encode(), endswith(), extract(),
group_concat(), group_spooky_hash(), gunzip(), gzip(),
anonymize(), char(), charindex(), decode(), encode(), endswith(),
extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
humanize_duration(), humanize_file_size(), instr(), leftstr(),
length(), logfmt2json(), lower(), ltrim(), padl(), padr(), printf(),
proper(), regexp_capture(), regexp_capture_into_json(), regexp_match(),
@ -3127,8 +3156,8 @@ For support questions, email:
str The string to pad
len The minimum desired length of the output string
See Also
char(), charindex(), decode(), encode(), endswith(), extract(),
group_concat(), group_spooky_hash(), gunzip(), gzip(),
anonymize(), char(), charindex(), decode(), encode(), endswith(),
extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
humanize_duration(), humanize_file_size(), instr(), leftstr(),
length(), logfmt2json(), lower(), ltrim(), padc(), padr(), printf(),
proper(), regexp_capture(), regexp_capture_into_json(), regexp_match(),
@ -3153,8 +3182,8 @@ For support questions, email:
str The string to pad
len The minimum desired length of the output string
See Also
char(), charindex(), decode(), encode(), endswith(), extract(),
group_concat(), group_spooky_hash(), gunzip(), gzip(),
anonymize(), char(), charindex(), decode(), encode(), endswith(),
extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
humanize_duration(), humanize_file_size(), instr(), leftstr(),
length(), logfmt2json(), lower(), ltrim(), padc(), padl(), printf(),
proper(), regexp_capture(), regexp_capture_into_json(), regexp_match(),
@ -3219,8 +3248,8 @@ For support questions, email:
X The argument to substitute at a given position in
the format.
See Also
char(), charindex(), decode(), encode(), endswith(), extract(),
group_concat(), group_spooky_hash(), gunzip(), gzip(),
anonymize(), char(), charindex(), decode(), encode(), endswith(),
extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
humanize_duration(), humanize_file_size(), instr(), leftstr(),
length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
proper(), regexp_capture(), regexp_capture_into_json(), regexp_match(),
@ -3247,8 +3276,8 @@ For support questions, email:
Parameter
str The string to capitalize.
See Also
char(), charindex(), decode(), encode(), endswith(), extract(),
group_concat(), group_spooky_hash(), gunzip(), gzip(),
anonymize(), char(), charindex(), decode(), encode(), endswith(),
extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
humanize_duration(), humanize_file_size(), instr(), leftstr(),
length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
printf(), regexp_capture(), regexp_capture_into_json(), regexp_match(),
@ -3370,8 +3399,8 @@ For support questions, email:
string.
content The captured value from the string.
See Also
char(), charindex(), decode(), encode(), endswith(), extract(),
group_concat(), group_spooky_hash(), gunzip(), gzip(),
anonymize(), char(), charindex(), decode(), encode(), endswith(),
extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
humanize_duration(), humanize_file_size(), instr(), leftstr(),
length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
printf(), proper(), regexp_capture_into_json(), regexp_match(),
@ -3403,8 +3432,8 @@ For support questions, email:
string.
content The captured values from the string.
See Also
char(), charindex(), decode(), encode(), endswith(), extract(),
group_concat(), group_spooky_hash(), gunzip(), gzip(),
anonymize(), char(), charindex(), decode(), encode(), endswith(),
extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
humanize_duration(), humanize_file_size(), instr(), leftstr(),
length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
printf(), proper(), regexp_capture(), regexp_match(), regexp_replace(),
@ -3425,8 +3454,8 @@ For support questions, email:
re The regular expression to use
str The string to test against the regular expression
See Also
char(), charindex(), decode(), encode(), endswith(), extract(),
group_concat(), group_spooky_hash(), gunzip(), gzip(),
anonymize(), char(), charindex(), decode(), encode(), endswith(),
extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
humanize_duration(), humanize_file_size(), instr(), leftstr(),
length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
printf(), proper(), regexp_capture(), regexp_capture_into_json(),
@ -3459,8 +3488,8 @@ For support questions, email:
groups with a backslash followed by the number of the group,
starting with 1.
See Also
char(), charindex(), decode(), encode(), endswith(), extract(),
group_concat(), group_spooky_hash(), gunzip(), gzip(),
anonymize(), char(), charindex(), decode(), encode(), endswith(),
extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
humanize_duration(), humanize_file_size(), instr(), leftstr(),
length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
printf(), proper(), regexp_capture(), regexp_capture_into_json(),
@ -3487,8 +3516,8 @@ For support questions, email:
replacement The string to replace any occurrences of
the old string with.
See Also
char(), charindex(), decode(), encode(), endswith(), extract(),
group_concat(), group_spooky_hash(), gunzip(), gzip(),
anonymize(), char(), charindex(), decode(), encode(), endswith(),
extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
humanize_duration(), humanize_file_size(), instr(), leftstr(),
length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
printf(), proper(), regexp_capture(), regexp_capture_into_json(),
@ -3512,8 +3541,8 @@ For support questions, email:
str The string to replicate.
N The number of times to replicate the string.
See Also
char(), charindex(), decode(), encode(), endswith(), extract(),
group_concat(), group_spooky_hash(), gunzip(), gzip(),
anonymize(), char(), charindex(), decode(), encode(), endswith(),
extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
humanize_duration(), humanize_file_size(), instr(), leftstr(),
length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
printf(), proper(), regexp_capture(), regexp_capture_into_json(),
@ -3532,8 +3561,8 @@ For support questions, email:
Parameter
str The string to reverse.
See Also
char(), charindex(), decode(), encode(), endswith(), extract(),
group_concat(), group_spooky_hash(), gunzip(), gzip(),
anonymize(), char(), charindex(), decode(), encode(), endswith(),
extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
humanize_duration(), humanize_file_size(), instr(), leftstr(),
length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
printf(), proper(), regexp_capture(), regexp_capture_into_json(),
@ -3554,8 +3583,8 @@ For support questions, email:
N The number of characters from the right side of the
string to return.
See Also
char(), charindex(), decode(), encode(), endswith(), extract(),
group_concat(), group_spooky_hash(), gunzip(), gzip(),
anonymize(), char(), charindex(), decode(), encode(), endswith(),
extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
humanize_duration(), humanize_file_size(), instr(), leftstr(),
length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
printf(), proper(), regexp_capture(), regexp_capture_into_json(),
@ -3621,8 +3650,8 @@ For support questions, email:
str The string to trim characters from the right side
chars The characters to trim. Defaults to spaces.
See Also
char(), charindex(), decode(), encode(), endswith(), extract(),
group_concat(), group_spooky_hash(), gunzip(), gzip(),
anonymize(), char(), charindex(), decode(), encode(), endswith(),
extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
humanize_duration(), humanize_file_size(), instr(), leftstr(),
length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
printf(), proper(), regexp_capture(), regexp_capture_into_json(),
@ -3675,8 +3704,8 @@ For support questions, email:
non-aggregate version defaults to 100. The aggregate
version uses the largest value in the inputs.
See Also
char(), charindex(), decode(), encode(), endswith(), extract(),
group_concat(), group_spooky_hash(), gunzip(), gzip(),
anonymize(), char(), charindex(), decode(), encode(), endswith(),
extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
humanize_duration(), humanize_file_size(), instr(), leftstr(),
length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
printf(), proper(), regexp_capture(), regexp_capture_into_json(),
@ -3699,8 +3728,8 @@ For support questions, email:
Parameter
str The string to hash
See Also
char(), charindex(), decode(), encode(), endswith(), extract(),
group_concat(), group_spooky_hash(), gunzip(), gzip(),
anonymize(), char(), charindex(), decode(), encode(), endswith(),
extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
humanize_duration(), humanize_file_size(), instr(), leftstr(),
length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
printf(), proper(), regexp_capture(), regexp_capture_into_json(),
@ -3780,8 +3809,8 @@ For support questions, email:
str The string to test
prefix The prefix to check in the string
See Also
char(), charindex(), decode(), encode(), endswith(), extract(),
group_concat(), group_spooky_hash(), gunzip(), gzip(),
anonymize(), char(), charindex(), decode(), encode(), endswith(),
extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
humanize_duration(), humanize_file_size(), instr(), leftstr(),
length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
printf(), proper(), regexp_capture(), regexp_capture_into_json(),
@ -3806,8 +3835,8 @@ For support questions, email:
source The string to filter
include The characters to include in the result
See Also
char(), charindex(), decode(), encode(), endswith(), extract(),
group_concat(), group_spooky_hash(), gunzip(), gzip(),
anonymize(), char(), charindex(), decode(), encode(), endswith(),
extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
humanize_duration(), humanize_file_size(), instr(), leftstr(),
length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
printf(), proper(), regexp_capture(), regexp_capture_into_json(),
@ -3863,8 +3892,8 @@ For support questions, email:
the value is negative, then the characters before the start
are returned.
See Also
char(), charindex(), decode(), encode(), endswith(), extract(),
group_concat(), group_spooky_hash(), gunzip(), gzip(),
anonymize(), char(), charindex(), decode(), encode(), endswith(),
extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
humanize_duration(), humanize_file_size(), instr(), leftstr(),
length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
printf(), proper(), regexp_capture(), regexp_capture_into_json(),
@ -4012,8 +4041,8 @@ For support questions, email:
right sides.
chars The characters to trim. Defaults to spaces.
See Also
char(), charindex(), decode(), encode(), endswith(), extract(),
group_concat(), group_spooky_hash(), gunzip(), gzip(),
anonymize(), char(), charindex(), decode(), encode(), endswith(),
extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
humanize_duration(), humanize_file_size(), instr(), leftstr(),
length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
printf(), proper(), regexp_capture(), regexp_capture_into_json(),
@ -4054,8 +4083,8 @@ For support questions, email:
Parameter
X The string to examine.
See Also
char(), charindex(), decode(), encode(), endswith(), extract(),
group_concat(), group_spooky_hash(), gunzip(), gzip(),
anonymize(), char(), charindex(), decode(), encode(), endswith(),
extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
humanize_duration(), humanize_file_size(), instr(), leftstr(),
length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
printf(), proper(), regexp_capture(), regexp_capture_into_json(),
@ -4082,8 +4111,8 @@ For support questions, email:
Parameter
str The string to convert.
See Also
char(), charindex(), decode(), encode(), endswith(), extract(),
group_concat(), group_spooky_hash(), gunzip(), gzip(),
anonymize(), char(), charindex(), decode(), encode(), endswith(),
extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
humanize_duration(), humanize_file_size(), instr(), leftstr(),
length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
printf(), proper(), regexp_capture(), regexp_capture_into_json(),
@ -4111,8 +4140,8 @@ For support questions, email:
node_attr The node's attributes stored in JSON object.
node_text The node's text value.
See Also
char(), charindex(), decode(), encode(), endswith(), extract(),
group_concat(), group_spooky_hash(), gunzip(), gzip(),
anonymize(), char(), charindex(), decode(), encode(), endswith(),
extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
humanize_duration(), humanize_file_size(), instr(), leftstr(),
length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
printf(), proper(), regexp_capture(), regexp_capture_into_json(),

@ -0,0 +1,3 @@
10.0.0.1 - - [20/Jul/2009:22:59:26 +0000] "GET /vmw/cgi/aberrant HTTP/1.0" 200 134 "-" "gPXE/0.9.7"
10.0.0.1 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/abject/ablaze/able.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
10.0.0.1 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/abject/ablaze/aboard.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"

@ -0,0 +1,198 @@
anonymize(bro_id_resp_h)
10.0.0.1
10.0.0.2
10.0.0.2
10.0.0.2
10.0.0.2
10.0.0.2
10.0.0.2
10.0.0.3
10.0.0.4
10.0.0.1
10.0.0.4
10.0.0.4
10.0.0.5
10.0.0.4
10.0.0.4
10.0.0.1
10.0.0.6
10.0.0.4
10.0.0.7
10.0.0.8
10.0.0.8
10.0.0.8
10.0.0.8
10.0.0.8
10.0.0.8
10.0.0.8
10.0.0.8
10.0.0.9
10.0.0.10
10.0.0.5
10.0.0.11
10.0.0.11
10.0.0.11
10.0.0.11
10.0.0.11
10.0.0.11
10.0.0.5
10.0.0.11
10.0.0.11
10.0.0.11
10.0.0.11
10.0.0.11
10.0.0.11
10.0.0.11
10.0.0.11
10.0.0.11
10.0.0.11
10.0.0.5
10.0.0.10
10.0.0.6
10.0.0.12
10.0.0.1
10.0.0.1
10.0.0.6
10.0.0.11
10.0.0.11
10.0.0.13
10.0.0.6
10.0.0.11
10.0.0.11
10.0.0.11
10.0.0.13
10.0.0.6
10.0.0.6
10.0.0.6
10.0.0.6
10.0.0.6
10.0.0.6
10.0.0.6
10.0.0.6
10.0.0.14
10.0.0.6
10.0.0.14
10.0.0.15
10.0.0.16
10.0.0.6
10.0.0.16
10.0.0.17
10.0.0.5
10.0.0.1
10.0.0.17
10.0.0.15
10.0.0.17
10.0.0.18
10.0.0.18
10.0.0.10
10.0.0.5
10.0.0.11
10.0.0.11
10.0.0.11
10.0.0.11
10.0.0.11
10.0.0.11
10.0.0.11
10.0.0.11
10.0.0.11
10.0.0.18
10.0.0.11
10.0.0.11
10.0.0.11
10.0.0.18
10.0.0.18
10.0.0.18
10.0.0.19
10.0.0.18
10.0.0.19
10.0.0.19
10.0.0.19
10.0.0.19
10.0.0.19
10.0.0.19
10.0.0.19
10.0.0.19
10.0.0.20
10.0.0.20
10.0.0.21
10.0.0.18
10.0.0.18
10.0.0.22
10.0.0.6
10.0.0.5
10.0.0.5
10.0.0.5
10.0.0.5
10.0.0.6
10.0.0.23
10.0.0.24
10.0.0.23
10.0.0.23
10.0.0.23
10.0.0.23
10.0.0.23
10.0.0.23
10.0.0.23
10.0.0.23
10.0.0.23
10.0.0.23
10.0.0.23
10.0.0.23
10.0.0.23
10.0.0.23
10.0.0.24
10.0.0.24
10.0.0.24
10.0.0.24
10.0.0.25
10.0.0.26
10.0.0.27
10.0.0.23
10.0.0.23
10.0.0.23
10.0.0.25
10.0.0.26
10.0.0.24
10.0.0.24
10.0.0.27
10.0.0.23
10.0.0.25
10.0.0.26
10.0.0.24
10.0.0.24
10.0.0.27
10.0.0.25
10.0.0.26
10.0.0.24
10.0.0.24
10.0.0.27
10.0.0.28
10.0.0.23
10.0.0.25
10.0.0.24
10.0.0.24
10.0.0.27
10.0.0.26
10.0.0.23
10.0.0.25
10.0.0.26
10.0.0.24
10.0.0.24
10.0.0.27
10.0.0.23
10.0.0.23
10.0.0.23
10.0.0.23
10.0.0.23
10.0.0.23
10.0.0.23
10.0.0.23
10.0.0.23
10.0.0.23
10.0.0.27
10.0.0.23
10.0.0.25
10.0.0.24
10.0.0.24
10.0.0.27
10.0.0.26

@ -57,6 +57,14 @@ run_cap_test ${lnav_test} -n -d /tmp/lnav.err \
-c ":write-view-to -" \
"${test_dir}/logfile_access_log.0"
run_cap_test ${lnav_test} -n -d /tmp/lnav.err \
-c ":write-view-to --anonymize -" \
"${test_dir}/logfile_access_log.0"
run_cap_test ${lnav_test} -n -d /tmp/lnav.err \
-c ":write-view-to --anonymize -" \
"${test_dir}/logfile_pretty.0"
run_cap_test ${lnav_test} -n -d /tmp/lnav.err \
-c ":filter-expr timeslice(:log_time_msecs, 'bad') is not null" \
"${test_dir}/logfile_multiline.0"

@ -115,3 +115,7 @@ run_cap_test ${lnav_test} -n \
-c ';SELECT log_body, extract(log_body) from vmw_log' \
-c ':write-json-to -' \
${test_dir}/logfile_vmw_log.0
run_cap_test ${lnav_test} -n \
-c ';SELECT anonymize(bro_id_resp_h) FROM bro_http_log' \
${test_dir}/logfile_bro_http.log.0

@ -0,0 +1,131 @@
/**
* Copyright (c) 2022, Timothy Stack
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Timothy Stack nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include "doctest/doctest.h"
#include "text_anonymizer.hh"
TEST_CASE("ipv4")
{
lnav::text_anonymizer ta;
CHECK(ta.next(string_fragment::from_const("127.0.1.1 says hi"))
== "10.0.0.1 says hi");
CHECK(ta.next(string_fragment::from_const("127.0.1.1 says hi"))
== "10.0.0.1 says hi");
CHECK(ta.next(string_fragment::from_const("u'127.0.1.1' says hi"))
== "u'10.0.0.1' says hi");
}
TEST_CASE("ipv6")
{
lnav::text_anonymizer ta;
CHECK(ta.next(
string_fragment::from_const("fe80::1887:2f2d:bc2e:8e41 says hi"))
== "2001:db8::1 says hi");
}
TEST_CASE("url")
{
lnav::text_anonymizer ta;
CHECK(ta.next(string_fragment::from_const("retrieving https://bob:abc@example.com/fooooooo22/192.168.1.33/barrrrr44?abcdef=foobar&ghijkl=123456&bazzer&ip=192.168.1.2#heading-2")) ==
"aback https://meerkat:67c93775f715ab8ab01178caf86713c6@achondroplasia.example.com/abaft22/10.0.0.1/abashed44?aberrant=abhorrent&abiding=123456&abject&ip=10.0.0.2#able-2");
}
TEST_CASE("email")
{
lnav::text_anonymizer ta;
CHECK(ta.next(string_fragment::from_const("hello support@lnav.org"))
== "aback meerkat@achondroplasia.example.com");
}
TEST_CASE("symbol")
{
lnav::text_anonymizer ta;
CHECK(ta.next(string_fragment::from_const(
"state is Constants.DOWNLOAD_STARTED"))
== "aback is Abandoned.ABASHED_ABERRANT");
}
TEST_CASE("date")
{
lnav::text_anonymizer ta;
CHECK(ta.next(string_fragment::from_const("2022-06-02T12:26:22.072Z"))
== "2022-06-02T12:26:22.072Z");
}
TEST_CASE("uuid")
{
lnav::text_anonymizer ta;
CHECK(ta.next(string_fragment::from_const(
"52556d7e-c34d-d7f9-73b6-f52ad939952e"))
== "bc8b6954-c2a4-e7f3-0e18-2fa4035db1c9");
}
TEST_CASE("MAC-address")
{
lnav::text_anonymizer ta;
CHECK(ta.next(string_fragment::from_const("ether f2:09:1a:a2:e3:e2"))
== "aback 00:00:5e:00:53:00");
}
TEST_CASE("hex-dump")
{
lnav::text_anonymizer ta;
CHECK(ta.next(string_fragment::from_const("key f2:09:1a:a2"))
== "key 2d:20:0d:cc");
}
TEST_CASE("cc")
{
lnav::text_anonymizer ta;
CHECK(ta.next(string_fragment::from_const("cc 6011 1111 1111 1117"))
== "cc 1a49 c794 31d9 3eb2");
CHECK(ta.next(string_fragment::from_const("cc 6011111111111117"))
== "cc 1a49c79431d93eb2");
}
TEST_CASE("xml")
{
lnav::text_anonymizer ta;
CHECK(ta.next(string_fragment::from_const("<o:gupdate xmlns:o=\"http://www.google.com/update2/request\" protocol=\"2.0\" version=\"KeystoneDaemon-1.2.0.7709\" ismachine=\"1\" requestid=\"{0DFDBCD1-5E29-4DFC-BD99-31A2397198FE}\">")) ==
"<o:gupdate xmlns:o=\"http://achondroplasia.example.com/aback2/abandoned\" protocol=\"2.0\" version=\"Abashed-1.2.0.7709\" ismachine=\"1\" requestid=\"{1ca0a968-cbe9-e75b-d00b-4859609878ea}\">");
}
Loading…
Cancel
Save