Editing Talk:1638: Backslashes
Please sign your posts with ~~~~ |
Warning: You are not logged in. Your IP address will be publicly visible if you make any edits. If you log in or create an account, your edits will be attributed to your username, along with other benefits.
The edit can be undone.
Please check the comparison below to verify that this is what you want to do, and then save the changes below to finish undoing the edit.
Latest revision | Your text | ||
Line 8: | Line 8: | ||
Oh, and by the way, isn't this the third comic to mention "Ba'al, the Soul Eater"? Maybe we should start a category. (Others are [http://www.explainxkcd.com/wiki/index.php/1246:_Pale_Blue_Dot 1246] (title text) and [http://www.explainxkcd.com/wiki/index.php/1419:_On_the_Phone 1419].) | Oh, and by the way, isn't this the third comic to mention "Ba'al, the Soul Eater"? Maybe we should start a category. (Others are [http://www.explainxkcd.com/wiki/index.php/1246:_Pale_Blue_Dot 1246] (title text) and [http://www.explainxkcd.com/wiki/index.php/1419:_On_the_Phone 1419].) | ||
[[Special:Contributions/173.245.54.29|173.245.54.29]] 06:14, 3 February 2016 (UTC) | [[Special:Contributions/173.245.54.29|173.245.54.29]] 06:14, 3 February 2016 (UTC) | ||
− | :Did that before seeing you comment, so yes I agree. --[[User:Kynde|Kynde]] ([[User talk:Kynde|talk]]) 09:47, 3 February 2016 (UTC | + | :[[:Category:Ba'al|Did that]] before seeing you comment, so yes I agree. --[[User:Kynde|Kynde]] ([[User talk:Kynde|talk]]) 09:47, 3 February 2016 (UTC) |
− | |||
− | |||
The last entry may also be an oblique reference to the infinitely-expandable recursive acronym "GOD = GOD Over Djinn" mentioned in Richard Hofstadter's Gödel, Escher, Bach.[[User:Taibhse|Taibhse]] ([[User talk:Taibhse|talk]]) 16:42, 3 February 2016 (UTC) | The last entry may also be an oblique reference to the infinitely-expandable recursive acronym "GOD = GOD Over Djinn" mentioned in Richard Hofstadter's Gödel, Escher, Bach.[[User:Taibhse|Taibhse]] ([[User talk:Taibhse|talk]]) 16:42, 3 February 2016 (UTC) | ||
;I don't think the regex is invalid | ;I don't think the regex is invalid | ||
− | |||
According to <tt>man grep</tt> you need to specify the <tt>-E</tt> option to use extended regex; without it unescaped parentheses are not interpreted, so they don't need to match. | According to <tt>man grep</tt> you need to specify the <tt>-E</tt> option to use extended regex; without it unescaped parentheses are not interpreted, so they don't need to match. | ||
Line 37: | Line 34: | ||
Outputs your bash_history, ordered by relative gibberishness. This was copied by hand from desktop to mobile, might well have a few typos.--[[Special:Contributions/162.158.90.208|162.158.90.208]] 10:04, 3 February 2016 (UTC) | Outputs your bash_history, ordered by relative gibberishness. This was copied by hand from desktop to mobile, might well have a few typos.--[[Special:Contributions/162.158.90.208|162.158.90.208]] 10:04, 3 February 2016 (UTC) | ||
− | |||
The problem in the comic is not with regexes per se but with situations when the entered text or expression passes through several interpreters, like bash -> grep/sed/awk, or program text -> external shell command. In such cases, you have to escape backslashes for each program in the sequence, and it gets worse if you have 'real' backslashes in the final text that you're processing with the utilities (Windows' file paths, for example). See https://en.wikipedia.org/wiki/Leaning_toothpick_syndrome. | The problem in the comic is not with regexes per se but with situations when the entered text or expression passes through several interpreters, like bash -> grep/sed/awk, or program text -> external shell command. In such cases, you have to escape backslashes for each program in the sequence, and it gets worse if you have 'real' backslashes in the final text that you're processing with the utilities (Windows' file paths, for example). See https://en.wikipedia.org/wiki/Leaning_toothpick_syndrome. | ||
Line 57: | Line 53: | ||
::::: Since no-one else seemed to want to, I just restructured that paragraph to make it more clear that if anything Harry Potter was inspired by the older examples, not the other way around. Expanded the LOTR reference and added DnD. If anything Randall is likely to be referencing either the Lovecraft references, or the concept of Elder in general. [[Special:Contributions/141.101.64.173|141.101.64.173]] 11:50, 4 February 2016 (UTC) | ::::: Since no-one else seemed to want to, I just restructured that paragraph to make it more clear that if anything Harry Potter was inspired by the older examples, not the other way around. Expanded the LOTR reference and added DnD. If anything Randall is likely to be referencing either the Lovecraft references, or the concept of Elder in general. [[Special:Contributions/141.101.64.173|141.101.64.173]] 11:50, 4 February 2016 (UTC) | ||
− | Attempting to add to the discussion: This regex is not necessarily invalid or incomprehensible. | + | Attempting to add to the discussion: This regex is not necessarily invalid or incomprehensible. It looks like he was looking for a line with a regular expression or definitely some code. You just have to work your way through the backslashes. Although it might be invalid depending on the precise rules. He has some unescaped closing brackets and closing parenthesis. If these have to always be escaped then the regex is invalid. If however you don't have to escape a closing bracket with no opening bracket, then things are fine. I'm not familiar enough with grep's regex parser to know how it handles that edge case. Presuming those unescaped paren and brackets are fine, his regex searches for: |
1. A backslash | 1. A backslash | ||
Line 90: | Line 86: | ||
Ninjaed by Cmancone, above. I agree with that result in every respect except for the start-of-string being potentially anything, but putting my own analysis in here because it took long enough to type! | Ninjaed by Cmancone, above. I agree with that result in every respect except for the start-of-string being potentially anything, but putting my own analysis in here because it took long enough to type! | ||
− | + | Depth-of-backslash might depend upon depth of utility. In Perl, <nowiki>''</nowiki>-quotes (among others) treat everything within as literal whilst ""-quotes (and variations) interpolates any special characters, variables, etc that you put in it. (Search for "Quote and Quote-like operators" in your favourite PerlDocs source.) '\sss' is a literal backslash followed by three 's' characters , while "\sss" is the special \s escape (a whitespace) followed by two further regular characters. You might need to define the first when you need to use it to provide a not-previously-escaped \s so that it might be escaped within another context. ''Or'' you define it as "\\sss" (escaped-\) the first time, as equivalent to '\sss'. But '\\sss' would be a literal that, later, could be interpreted as an escaped-\ to the input of a further context where the \s finally becomes 'match a whitespace'. | |
− | Depth-of-backslash might depend upon depth of utility. In Perl, <nowiki>''</nowiki>-quotes (among others) treat everything within as literal whilst ""-quotes (and variations) interpolates any special characters, variables, etc that you put in it. (Search for "Quote and Quote-like operators" in your favourite PerlDocs source.) '\sss' is a literal backslash followed by three 's' characters , while "\sss" is the special \s escape (a whitespace) followed by two further regular characters. You might need to define the first when you need to use it to provide a not-previously-escaped \s so that it might be escaped within another context. ''Or'' you define it as "\\sss" (escaped-\) the first time, as equivalent to '\sss'. But '\\sss' would be a literal that, later, could be interpreted as an escaped-\ to the input of a further context where the \s finally becomes 'match a whitespace'. | ||
− | '\\\sss' would be literal, whilst "\\\sss" could be equivalent to '\ ss' (literal backslash, literal space, rest of characters). Then, instead of literal '\\sss', for some purpose, you could interpolate two escaped-backslashes "\\\\sss"... and so on. | + | '\\\sss' would be literal, whilst "\\\sss" could be equivalent to '\ ss' (literal backslash, literal space, rest of characters). Then, instead of literal '\\sss', for some purpose, you could interpolate two escaped-backslashes "\\\\sss"... and so on. |
− | Meanwhile I ''think'', just from visual inspection, "'''\\\[[(].*\\\[\])][^)\]]*$'''" in Bash should obey the interpolation rules quite nicely. The first two characters must be a literal backslash (from the escaped-backslash) and a literal open-square bracket (again, escaped). The next open-square and the close-square shortly after depict a character class that contains only an open-parenthesis, and could have been written as '''\('''. | + | Meanwhile I ''think'', just from visual inspection, "'''\\\[[(].*\\\[\])][^)\]]*$'''" in Bash should obey the interpolation rules quite nicely. The first two characters must be a literal backslash (from the escaped-backslash) and a literal open-square bracket (again, escaped). The next open-square and the close-square shortly after depict a character class that contains only an open-parenthesis, and could have been written as '''\('''. |
− | The '''.*''' indicates zero-or-more (the asterix) instances of ''any'' character (the dot). There is then a literal backslash (from the next '''\\''' duo) and a literal open-square (the '''\[''' pair) and close-square (the '''\]''' pair). The ''')''' is literal and does not need escaping (as a parenthesis group had not yet been opened), as is the next ''']''' character. To be sure, I would have written these two as the pair escapes '''\)\]''', but horses for courses... | + | The '''.*''' indicates zero-or-more (the asterix) instances of ''any'' character (the dot). There is then a literal backslash (from the next '''\\''' duo) and a literal open-square (the '''\[''' pair) and close-square (the '''\]''' pair). The ''')''' is literal and does not need escaping (as a parenthesis group had not yet been opened), as is the next ''']''' character. To be sure, I would have written these two as the pair escapes '''\)\]''', but horses for courses... |
− | Then there's another character class (the next '''[''' and the final ''']''') required zero-or-more times (the asterix) to use up all the rest of the characters to the end (the ending '''$''' character). As there was no '''^''' character (a.k.a. caret/circumflex/etc) at the start, the match isn't bothered about what unmatched characters appear before the original '''\('''. This character class, however, starts with a '''^''' which in this context (the very first character of a character-class definition, not somewhere where an entire match-string starts) indicates negation of the following selection, so it is all characters ''but'' those specified, which is the regular close-parenthesis and (because it needs to be contained within a '''[]''' pair) the escaped close-square. | + | Then there's another character class (the next '''[''' and the final ''']''') required zero-or-more times (the asterix) to use up all the rest of the characters to the end (the ending '''$''' character). As there was no '''^''' character (a.k.a. caret/circumflex/etc) at the start, the match isn't bothered about what unmatched characters appear before the original '''\('''. This character class, however, starts with a '''^''' which in this context (the very first character of a character-class definition, not somewhere where an entire match-string starts) indicates negation of the following selection, so it is all characters ''but'' those specified, which is the regular close-parenthesis and (because it needs to be contained within a '''[]''' pair) the escaped close-square. |
− | So, all matching strings must start with '''\[(''', i.e. the backslash, open-square and open-paren. They can continue with ''any'' further text, before then having a '''\[])]''', i.e. backslash, open-and-close-squares and close-paren, close-square. After this, the match continues just as long as there are no non-closing square/classic brackets before the ending. | + | So, all matching strings must start with '''\[(''', i.e. the backslash, open-square and open-paren. They can continue with ''any'' further text, before then having a '''\[])]''', i.e. backslash, open-and-close-squares and close-paren, close-square. After this, the match continues just as long as there are no non-closing square/classic brackets before the ending. |
− | The minimum matching literal string would be '''\[(\[])]''' with longer variants being of the form '''X\[(Y\[])]Z''' where X and Y can be replaced by anything (or be absent), and Z can be replaced by anything (or absent!) ''so long as it doesn't contain possibly relevent close-brackets!''. The latter stipulation is likely because the Y (and X) ''is'' allowed to contain these characters, and for some reason you don't want to confuse the test by finding some other '''\[])]''' segment within the X/Y-zones. (In this context, it doesn't actually seem to matter too much. But it might do in ways I haven't spotted or just be a hang-over from a prior permutation of the test.) | + | The minimum matching literal string would be '''\[(\[])]''' with longer variants being of the form '''X\[(Y\[])]Z''' where X and Y can be replaced by anything (or be absent), and Z can be replaced by anything (or absent!) ''so long as it doesn't contain possibly relevent close-brackets!''. The latter stipulation is likely because the Y (and X) ''is'' allowed to contain these characters, and for some reason you don't want to confuse the test by finding some other '''\[])]''' segment within the X/Y-zones. (In this context, it doesn't actually seem to matter too much. But it might do in ways I haven't spotted or just be a hang-over from a prior permutation of the test.) |
− | The "grep -o" function is working on the output to the file being '''cat'''ed (there are alternate ways of doing this that some people might prefer), to only accept the lines in the file that match the '''X\[(Y\[])]Z''' string. These lines would appear to be lines of out.txt (a fairly generic name that reveals little to its original purpose) that are well-formed for some other purpose. A safety-escaped (i.e. not to be taken literally by any simple parser) '''[]'''-grouping containing a '''()'''-group (''not'' escaped, perhaps reasonably in context) containing potentially random text followed by an empty '''[]''' pair (again, safety-escaped). Depending on the source, the empty '''[]'''-pair could mean many things, as with the other layers. And the lines may end with any further text. | + | The "grep -o" function is working on the output to the file being '''cat'''ed (there are alternate ways of doing this that some people might prefer), to only accept the lines in the file that match the '''X\[(Y\[])]Z''' string. These lines would appear to be lines of out.txt (a fairly generic name that reveals little to its original purpose) that are well-formed for some other purpose. A safety-escaped (i.e. not to be taken literally by any simple parser) '''[]'''-grouping containing a '''()'''-group (''not'' escaped, perhaps reasonably in context) containing potentially random text followed by an empty '''[]''' pair (again, safety-escaped). Depending on the source, the empty '''[]'''-pair could mean many things, as with the other layers. And the lines may end with any further text. |
− | The "out.txt" file might be the result of a prior Grep (string-search function) quote possibly scanning code for lines of particular importance by another pattern and dumping the results to out.txt for further perusal. And then Randall finds the need to dig further into the first result by extracting just those already selected that all have the '''X\[(Y\[])Z]'''-ish pattern to them. | + | The "out.txt" file might be the result of a prior Grep (string-search function) quote possibly scanning code for lines of particular importance by another pattern and dumping the results to out.txt for further perusal. And then Randall finds the need to dig further into the first result by extracting just those already selected that all have the '''X\[(Y\[])Z]'''-ish pattern to them. |
− | But I could be wrong, and that's way too long for an official explanation. | + | But I could be wrong, and that's way too long for an official explanation. |
(Perhaps just something like the penultimate paragraph, if we're not entirely mistaken?) [[Special:Contributions/162.158.152.89|162.158.152.89]] 14:14, 3 February 2016 (UTC) | (Perhaps just something like the penultimate paragraph, if we're not entirely mistaken?) [[Special:Contributions/162.158.152.89|162.158.152.89]] 14:14, 3 February 2016 (UTC) | ||
− | The regex is supposed to be looking for | + | The regex is supposed to be looking for: |
\\\ backslash | \\\ backslash | ||
[[(] [ or ( | [[(] [ or ( | ||
Line 122: | Line 117: | ||
$ end of string | $ end of string | ||
− | The first problem is that you're not supposed to escape ] in a [...], and it also has to be first in the grouping (unless negated with a ^) It should be [][)] or something similar. | + | The first problem is that you're not supposed to escape ] in a [...], and it also has to be first in the grouping (unless negated with a ^) It should be [][)] or something similar. |
− | + | The second problem is the same. The last bit should be [^])]*$ and not [^)\]]*$. [[User:Khris|Khris]] ([[User talk:Khris|talk]]) 14:24, 3 February 2016 (UTC) | |
− | The second problem is the same. The last bit should be [^])]*$ and not [^)\]]*$. [[User:Khris|Khris]] ([[User talk:Khris|talk]]) 14:24, 3 February 2016 (UTC) | ||
Line 131: | Line 125: | ||
− | The regex relies on several special cases (*surprise*). | + | The regex relies on several special cases (*surprise*). |
First: bash double-quote expansion (see [https://www.gnu.org/software/bash/manual/html_node/Double-Quotes.html#Double-Quotes]). Perhaps non-intuitively, \\\ followed by a character that \ doesn't escape is an escaped backslash followed by a literal backslash, effectively the same as \\\\ followed by that same non-escaped character. After bash double-quote expansion, this results in: | First: bash double-quote expansion (see [https://www.gnu.org/software/bash/manual/html_node/Double-Quotes.html#Double-Quotes]). Perhaps non-intuitively, \\\ followed by a character that \ doesn't escape is an escaped backslash followed by a literal backslash, effectively the same as \\\\ followed by that same non-escaped character. After bash double-quote expansion, this results in: | ||
Line 171: | Line 165: | ||
;Example of a match | ;Example of a match | ||
− | |||
First, the shell will do some escaping substitution. So, in order to easily read it, let's see what grep really receives: | First, the shell will do some escaping substitution. So, in order to easily read it, let's see what grep really receives: | ||
Line 202: | Line 195: | ||
:You're making the same mistake Randall did: while many (most?) regex dialects use \ as escape inside a character class, this is not true for grep's default syntax. I've expanded that interpretation in my comment below, however the analysis by 108.162.228.167 is a correct explanation of how this expression is ''actually'' interpreted by grep. --[[Special:Contributions/141.101.75.185|141.101.75.185]] 15:42, 4 February 2016 (UTC) | :You're making the same mistake Randall did: while many (most?) regex dialects use \ as escape inside a character class, this is not true for grep's default syntax. I've expanded that interpretation in my comment below, however the analysis by 108.162.228.167 is a correct explanation of how this expression is ''actually'' interpreted by grep. --[[Special:Contributions/141.101.75.185|141.101.75.185]] 15:42, 4 February 2016 (UTC) | ||
− | Your analysis is thorough and correct, however it is unlikely this is what the regex was intended to accomplish. | + | Your analysis is thorough and correct, however it is unlikely this is what the regex was intended to accomplish. More likely, Randall is more accustomed to other regex dialects such as Perl(-compatible) regex where a backslash ''does'' work to escape special characters inside a character class. Under that assumption the regex (with some whitespace inserted for readability) would break up as: |
* <code>\\ [[(]</code> an escaped opening bracket or paren | * <code>\\ [[(]</code> an escaped opening bracket or paren | ||
* <code>.*</code> anything | * <code>.*</code> anything | ||
Line 208: | Line 201: | ||
* <code>[^)\]]* $</code> no closing bracket or paren occurring on the remainder of the line | * <code>[^)\]]* $</code> no closing bracket or paren occurring on the remainder of the line | ||
Although the final condition is still a bit obscure, this still makes a ''lot'' more sense. Unfortunately it also crushes Randall's hope the regex worked as intended, since this simply isn't how the expression is parsed with grep's default syntax (which is why I always use <code>grep -P</code>). --[[Special:Contributions/141.101.75.185|141.101.75.185]] 15:34, 4 February 2016 (UTC) | Although the final condition is still a bit obscure, this still makes a ''lot'' more sense. Unfortunately it also crushes Randall's hope the regex worked as intended, since this simply isn't how the expression is parsed with grep's default syntax (which is why I always use <code>grep -P</code>). --[[Special:Contributions/141.101.75.185|141.101.75.185]] 15:34, 4 February 2016 (UTC) | ||
− | + | ||
Did anyone notice the [https://en.wikipedia.org/wiki/Cat_%28Unix%29#Useless_use_of_cat Useless Use of Cat]? [[Special:Contributions/141.101.106.101|141.101.106.101]] 19:36, 4 February 2016 (UTC) | Did anyone notice the [https://en.wikipedia.org/wiki/Cat_%28Unix%29#Useless_use_of_cat Useless Use of Cat]? [[Special:Contributions/141.101.106.101|141.101.106.101]] 19:36, 4 February 2016 (UTC) | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− |