TE
科技回声
首页24小时热榜最新最佳问答展示工作
GitHubTwitter
首页

科技回声

基于 Next.js 构建的科技新闻平台,提供全球科技新闻和讨论内容。

GitHubTwitter

首页

首页最新最佳问答展示工作

资源链接

HackerNews API原版 HackerNewsNext.js

© 2025 科技回声. 版权所有。

Regex character "$" doesn't mean "end-of-string"

437 点作者 BerislavLopac大约 1 年前

53 条评论

Karellen大约 1 年前
&gt; Folks who&#x27;ve worked with regular expressions before might know about ^ meaning &quot;start-of-string&quot; and correspondingly see $ as &quot;end-of-string&quot;.<p>Huh. I always think of them as &quot;start-of-line&quot; and &quot;end-of-line&quot;. I mean, a lot of the time when I&#x27;m working with regexes, I&#x27;m working with text a line at a time so the effect is the same, but that doesn&#x27;t change how I think of those operators.<p>Maybe because a fair amount of the work I do with regexes (and, probably, how I was introduced to them) is via `grep`, so I&#x27;m often thinking of the inputs as &quot;lines&quot; rather than &quot;strings&quot;?
评论 #39766960 未加载
评论 #39764657 未加载
评论 #39764757 未加载
评论 #39764584 未加载
评论 #39766298 未加载
评论 #39764385 未加载
评论 #39765053 未加载
评论 #39768777 未加载
评论 #39769272 未加载
SAI_Peregrinus大约 1 年前
POSIX regexes and Python regexes are different. In general, you need to reference the regex documentation for <i>your implementation</i>, since the syntax is not universal.<p>Per POSIX chapter 9[1]:<p>9.2 … &quot;The use of regular expressions is generally associated with text processing. REs (BREs and EREs) operate on text strings; that is, zero or more characters followed by an end-of-string delimiter (typically NUL). Some utilities employing regular expressions limit the processing to lines; that is, zero or more characters followed by a &lt;newline&gt;.&quot;<p>and 9.3.8 … &quot;A &lt;dollar-sign&gt; ( &#x27;$&#x27; ) shall be an anchor when used as the last character of an entire BRE. The implementation may treat a &lt;dollar-sign&gt; as an anchor when used as the last character of a subexpression. The &lt;dollar-sign&gt; shall anchor the expression (or optionally subexpression) to the end of the string being matched; the &lt;dollar-sign&gt; can be said to match the end-of-string following the last character.&quot;<p>combine to mean that $ may match the end of string OR the end of the line, and it&#x27;s up to the utility (or mode) to define which. Most of the common utilities (grep, sed, awk, Python, etc) treat it as end of line by default, since they operate on lines by default.<p>THERE IS NO SINGLE UNIVERSAL REGULAR EXPRESSION SYNTAX. You cannot reliably read or write regular expressions without knowing which language &amp; options are being used.<p>[1] <a href="https:&#x2F;&#x2F;pubs.opengroup.org&#x2F;onlinepubs&#x2F;9699919799&#x2F;basedefs&#x2F;V1_chap09.html" rel="nofollow">https:&#x2F;&#x2F;pubs.opengroup.org&#x2F;onlinepubs&#x2F;9699919799&#x2F;basedefs&#x2F;V1...</a>
PuffinBlue大约 1 年前
This seems like the perfect opportunity to introduce those unfamiliar to Robert Elder. He makes cool YouTube[0] and blog content[1] and has a series on regular expressions[2] and does some quite deep dives into the differing behaviour of the different tools that implement the various versions.<p>His latest on the topic is cool too: <a href="https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=ys7yUyyQA-Y" rel="nofollow">https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=ys7yUyyQA-Y</a><p>He&#x27;s has quite a lot of content that HN folks might be interested in I think, like the reality and woes of consulting[3]<p>[0] <a href="https:&#x2F;&#x2F;www.youtube.com&#x2F;@RobertElderSoftware" rel="nofollow">https:&#x2F;&#x2F;www.youtube.com&#x2F;@RobertElderSoftware</a><p>[1] <a href="https:&#x2F;&#x2F;blog.robertelder.org&#x2F;" rel="nofollow">https:&#x2F;&#x2F;blog.robertelder.org&#x2F;</a><p>[2] <a href="https:&#x2F;&#x2F;blog.robertelder.org&#x2F;regular-expressions&#x2F;" rel="nofollow">https:&#x2F;&#x2F;blog.robertelder.org&#x2F;regular-expressions&#x2F;</a><p>[3] <a href="https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=cK87ktENPrI" rel="nofollow">https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=cK87ktENPrI</a>
评论 #39764400 未加载
评论 #39765354 未加载
xlii大约 1 年前
Regexp was one of the first things I truly internalized years ago when I was discovering Perl (which still lives in a cozy place in my heart due to a lovely “Camel” book).<p>Today most important bit of information is knowledge that implementations differ and I made a habit of pulling reference sheet for a thing I work with.<p>E.g. Emacs Regexp annoyingly doesn’t have word in form of “\w” but uses “\s_-“ (or something no reference sheet on screen) as character class (but Emacs has the best documentation and discoverability - a hill I’m willing to die on)<p>Some utilities require parenthesis escaping and some not. Sometimes this behavior is configurable and sometimes it’s not.<p>I lived through whole confusion, annoyance, denial phase and now I just accept it. Concept is the same everywhere but flavor changes.
评论 #39764942 未加载
评论 #39767568 未加载
onion2k大约 1 年前
I can hear thousands of bad hiring manager&#x27;s adding &#x27;How do you match the end of a string in a regex?&#x27; to their list of &#x27;Ha! You don&#x27;t know the trick!&#x27; questions designed to catch out candidates.
评论 #39764593 未加载
tyingq大约 1 年前
Seems odd to leave Perl off the list, given it&#x27;s regex related.<p>Here&#x27;s the explanation for $ in the perlre docs:<p><pre><code> $ Match the end of the string (or before newline at the end of the string; or before any newline if &#x2F;m is used)</code></pre>
评论 #39765572 未加载
perlgeek大约 1 年前
Raku (formerly Perl 6) has picked ^ and $ for start-of-string and end-of-string, and has introduced ^^ and $$ for start-of-line and end-of-line. No multi line mode is available or necessary. (There&#x27;s also \h for horizontal and \v for vertical whitespace)<p>That&#x27;s one of the benefits of a complete rethink&#x2F;rewrite, you can learn from the fact that the old behavior surprised people.
评论 #39767039 未加载
评论 #39767181 未加载
评论 #39828524 未加载
beardyw大约 1 年前
Does anyone consider RegEx to be standardised? Moving to a new context is always a relearning exercise in my experience.
评论 #39764164 未加载
评论 #39764703 未加载
评论 #39764313 未加载
评论 #39764160 未加载
评论 #39765847 未加载
评论 #39764180 未加载
评论 #39764159 未加载
评论 #39765563 未加载
评论 #39764245 未加载
danbruc大约 1 年前
People are confused about strings and lines. A string is a sequence of characters, a line can be two different things. If you consider the newline a line terminator, then a line is a sequence of non-newline characters - possibly zero - plus a newline. If there is no new-line at the end, then it is not a [complete] line. That is what POSIX uses. If you consider the newline a line separator, then a line is a sequence of non-newline characters - possibly zero. In either case, the content of the line ends before the newline, either because the newline terminates the line or because it separates the line from the next. [1]<p>The semantics of ^ and $ is based on lines - whether single-line or multi-line mode. For string based semantics - which you could also think of as entire file if you are dealing with files - use \A and \Z or their equivalents.<p>[1] Both interpretations have their merits. If you transmit text over a serial connection, it is useful to have a newline as line terminator so that you know when you received a complete line. If you put text into text files, it might arguably be easier to look at a newline as a line separator because then you can not have a invalid last line. On the other hand having line terminators in text files allows you to detect incompletely written lines.
homakov大约 1 年前
This led to a few serious bugs in Ruby-based apps. Always use \A\z<p><a href="https:&#x2F;&#x2F;homakov.blogspot.com&#x2F;2012&#x2F;05&#x2F;saferweb-injects-in-various-ruby.html" rel="nofollow">https:&#x2F;&#x2F;homakov.blogspot.com&#x2F;2012&#x2F;05&#x2F;saferweb-injects-in-var...</a><p><a href="https:&#x2F;&#x2F;sakurity.com&#x2F;blog&#x2F;2015&#x2F;02&#x2F;28&#x2F;openuri.html" rel="nofollow">https:&#x2F;&#x2F;sakurity.com&#x2F;blog&#x2F;2015&#x2F;02&#x2F;28&#x2F;openuri.html</a><p><a href="https:&#x2F;&#x2F;sakurity.com&#x2F;blog&#x2F;2015&#x2F;06&#x2F;04&#x2F;mongo_ruby_regexp.html" rel="nofollow">https:&#x2F;&#x2F;sakurity.com&#x2F;blog&#x2F;2015&#x2F;06&#x2F;04&#x2F;mongo_ruby_regexp.html</a>
somat大约 1 年前
Structural regexes as found in the sam editor are an obscure but well engineered regex engine. I am far from an expert but my main takeaway from them is that most regex engines have an implied structure built around &quot;lines&quot; of text. While you can work around this, it is awkward. Structural regexes allow you to explicitly define the structure of a match, that is, you get to tell the engine what a &quot;line&quot; is.<p><a href="http:&#x2F;&#x2F;man.cat-v.org&#x2F;plan_9&#x2F;1&#x2F;sam" rel="nofollow">http:&#x2F;&#x2F;man.cat-v.org&#x2F;plan_9&#x2F;1&#x2F;sam</a>
vitiral大约 1 年前
In Lua it&#x27;s only the start&#x2F;end of the string<p>&gt; A pattern is a sequence of pattern items. A caret &#x27;^&#x27; at the beginning of a pattern anchors the match at the beginning of the subject string. A &#x27;$&#x27; at the end of a pattern anchors the match at the end of the subject string. At other positions, &#x27;^&#x27; and &#x27;$&#x27; have no special meaning and represent themselves.<p><a href="https:&#x2F;&#x2F;www.lua.org&#x2F;manual&#x2F;5.3&#x2F;manual.html#6.4.1" rel="nofollow">https:&#x2F;&#x2F;www.lua.org&#x2F;manual&#x2F;5.3&#x2F;manual.html#6.4.1</a><p>Lua&#x27;s pattern matching is much simpler than regexes though.<p>&gt; Unlike several other scripting languages, Lua does not use POSIX regular expressions (regexp) for pattern matching. The main reason for this is size: A typical implementation of POSIX regexp takes more than 4,000 lines of code. This is bigger than all Lua standard libraries together. In comparison, the implementation of pattern matching in Lua has less than 500 lines.<p><a href="https:&#x2F;&#x2F;www.lua.org&#x2F;pil&#x2F;20.1.html" rel="nofollow">https:&#x2F;&#x2F;www.lua.org&#x2F;pil&#x2F;20.1.html</a>
评论 #39767901 未加载
librasteve大约 1 年前
I am surprised that the OP does not include perl5 in their table.<p>In raku (aka perl6) Regexes were reinvented by Larry Wall (the creator of perl which made perlRE the de facto regex standard)<p>Here&#x27;s what he does with $:<p>(<a href="https:&#x2F;&#x2F;docs.raku.org&#x2F;language&#x2F;regexes#Start_of_string_and_end_of_string" rel="nofollow">https:&#x2F;&#x2F;docs.raku.org&#x2F;language&#x2F;regexes#Start_of_string_and_e...</a>)<p>* The $ anchor only matches at the end of the string<p>* The $$ anchor matches at the end of a logical line. That is, before a newline character, or at the end of the string when the last character is not a newline character.
aftbit大约 1 年前
Wait, in non-multiline mode, it only matches _one_ trailing newline? And not any other whitespace, including \r or \r\n? That is indeed surprising behavior. Why? Why not just make it end of string like the author expected?<p><pre><code> &gt;&gt;&gt; import re &gt;&gt;&gt; bool(re.search(&#x27;abc$&#x27;, &#x27;abc&#x27;)) True &gt;&gt;&gt; bool(re.search(&#x27;abc$&#x27;, &#x27;abc\n&#x27;)) True &gt;&gt;&gt; bool(re.search(&#x27;abc$&#x27;, &#x27;abc\n\n&#x27;)) False &gt;&gt;&gt; bool(re.search(&#x27;abc$&#x27;, &#x27;abc &#x27;)) False &gt;&gt;&gt; bool(re.search(&#x27;abc$&#x27;, &#x27;abc\t&#x27;)) False &gt;&gt;&gt; bool(re.search(&#x27;abc$&#x27;, &#x27;abc\r&#x27;)) False &gt;&gt;&gt; bool(re.search(&#x27;abc$&#x27;, &#x27;abc\r\n&#x27;)) False</code></pre>
jewel大约 1 年前
This has security implications! Example exploitable ruby code:<p><pre><code> unless person_id =~ &#x2F;^\d+$&#x2F; abort &quot;Bad person ID&quot; end sql = &quot;select * from people where person_id = #{person_id}&quot; </code></pre> In addition to injection attacks, this also can bite people when parsing headers, where a bad header is allowed to sneak past a filter.
评论 #39769041 未加载
评论 #39768401 未加载
hans_castorp大约 1 年前
Fun fact: in Postgres, &#x27;cat\n&#x27; matches &#x27;cat$&#x27; when the so called &quot;weird&quot; newline matching is enabled :)<p><a href="https:&#x2F;&#x2F;www.postgresql.org&#x2F;docs&#x2F;current&#x2F;functions-matching.html#POSIX-EMBEDDED-OPTIONS-TABLE" rel="nofollow">https:&#x2F;&#x2F;www.postgresql.org&#x2F;docs&#x2F;current&#x2F;functions-matching.h...</a>
masswerk大约 1 年前
As for the good old reference implementation (not <i>&quot;Parameter Efficient Reinforcement Learning&quot;</i>):<p><pre><code> my $string = &quot;cat\n&quot;; &#x2F;cat$&#x2F;s -&gt; true &#x2F;cat\Z&#x2F;s -&gt; true &#x2F;cat\z&#x2F;s -&gt; false</code></pre>
nebulous1大约 1 年前
The fact that there are so many different peculiarities in different regex systems has always raised the hairs on the back of my neck. As in when a tool accepts a regex and I have to a trawl the manual to find out exactly what regex is acceptable to it.
pjc50大约 1 年前
Special misery case: Visual Studio supports regex search, where &#x27;$&#x27; matches \n.<p>The end of line character is usually the standard Windows \r\n.<p>Yes, that means if you want to really match the end of line you have to match &quot;\r$&quot;. So broken.
评论 #39764332 未加载
评论 #39764284 未加载
wruza大约 1 年前
<i>By default, &#x27;$&#x27; only matches at the end of the string and immediately before the newline (if any) at the end of the string.</i><p>The rationale was probably &quot;it should be easier to match input strings&quot; and now it&#x27;s harder for everyone.
gorjusborg大约 1 年前
If you really want to learn regex, you&#x27;ll have a hard time piecing it all together via blog posts.<p>Brad Freidl&#x27;s Mastering Regular Expressions is a good book to read if you want to stop being surprised&#x2F;lost.<p>I&#x27;ll admit I stopped at the dive into DFA&#x2F;NFA engine details.
评论 #39773225 未加载
m0rissette大约 1 年前
Why isn’t Perl anywhere on that chart when mentioning regex?
评论 #39765352 未加载
ghusbands大约 1 年前
&gt; Note: The table of data was gathered from regex101.com, I didn&#x27;t test using the actual runtimes.<p>Has anyone confirmed this behaviour directly against the runtimes&#x2F;languages? Newlines at the end of a string are certainly something that could get lost in transit inside an online service involving multiple runtimes.
评论 #39765142 未加载
评论 #39764335 未加载
评论 #39764740 未加载
评论 #39764232 未加载
评论 #39764522 未加载
ikiris大约 1 年前
this is mostly due to the different types of regex and less about it being platform dependent. $ was end of string in pcre which is the &quot;old&quot; perl compatible regex. python has its own which has quirks as mentioned, re2 is another option in go for example, and i think rust has its own version as well iirc.
评论 #39764121 未加载
评论 #39764046 未加载
评论 #39764241 未加载
javier_e06大约 1 年前
I would hold a code review hostage if any file does not end with an empty new line.<p>My reasoning would be if the file is transmitted and gets truncated nobody would know for sure if it does not end a new line. Brownie points if this is code end has a comment that the files ends there.<p>The article calls computer languages platforms but the are computer languages. Bash is not included. Weird. I believe the most common use of regular expressions is the use of grep or egrep with bash or some other shell but, who knows. Maybe I am hanging with the wrong crowd.
weinzierl大约 1 年前
The table in the article makes this look complicated, but it really isn&#x27;t. All the cases in the article can be grouped into two families:<p>- The JS&#x2F;Go&#x2F;Rust family, which treats $ like \z and does not support \Z at all<p>- The Java, .NET, PHP, Python family, which treats $ like \Z and may or may not (Python) support \z.<p>\Z does away with \n before the end of the string, while \z treats \n as a regular character. For multiline $ the distinction doesn&#x27;t matter, because \n <i>is</i> the end.<p>Really the only deviation from the rule is Python&#x27;s \Z, which is indeed weird.
pksebben大约 1 年前
Regex would really benefit from a comprehensive industrial standard. It&#x27;s such a powerful tool that you have to keep relearning whenever you switch contexts.
Scubabear68大约 1 年前
In 30 years of developing software I don’t think I ever used multi-line regexp even once.
评论 #39767146 未加载
评论 #39765443 未加载
Existing4190大约 1 年前
perlre Metacharacters documentation states: $ Match the end of the string (or before newline at the end of the string; or before any newline if &#x2F;m is used)<p>(&#x2F;m enables multiline mode)
frou_dh大约 1 年前
Something I found really surprising about Python&#x27;s regexp implementation is that it doesn&#x27;t support the typical character classes like [:alnum:] etc.<p>It must be some kind of philosophical objection because there&#x27;s no way something with as much water under the bridge as Python simply hasn&#x27;t got around to it.
mmh0000大约 1 年前
<p><pre><code> &gt; So if you&#x27;re trying to match a string without a newline at the end, you can&#x27;t only use $ in Python! My expectation was having multiline mode disabled wouldn&#x27;t have had this newline-matching behavior, but that isn&#x27;t the case. </code></pre> I would argue this is correct behavior, a &quot;line&quot; isn&#x27;t a &quot;line&quot; if it doesn&#x27;t end with \n.[1]<p><pre><code> &gt; 3.206 Line - A sequence of zero or more non- &lt;newline&gt; characters plus a terminating &lt;newline&gt; character. </code></pre> [1] <a href="https:&#x2F;&#x2F;pubs.opengroup.org&#x2F;onlinepubs&#x2F;9699919799&#x2F;basedefs&#x2F;V1_chap03.html#tag_03_206" rel="nofollow">https:&#x2F;&#x2F;pubs.opengroup.org&#x2F;onlinepubs&#x2F;9699919799&#x2F;basedefs&#x2F;V1...</a>
评论 #39778736 未加载
smlacy大约 1 年前
It&#x27;s easy to get the canonical answer:<p>$ man pcre2syntax<p>Where you&#x27;ll find the following block under ANCHORS AND SIMPLE ASSERTIONS:<p><pre><code> $ end of subject also before newline at end of subject also before internal newline in multiline mode </code></pre> So all the cases of &quot;newline at&#x2F;before end of subject&quot; are covered here. Then, the question becomes &quot;what is a subject?&quot; Is it line-by-line? Are newlines included? What if we want multiline matching? That&#x27;s where re.MULTILINE comes from, it&#x27;s not &quot;multiline matching&quot; (sort of) it&#x27;s &quot;what is the subject of the regular expression that we&#x27;re matching against&quot;
pmarreck大约 1 年前
The results did not surprise me. The fact that everyone is in agreement that &quot;cat$&quot; matches &quot;cat&quot; and not &quot;cat\n&quot; if multiline is off did not surprise me. \n is implicitly a multiline-contextual character to me. In other words, if you didn&#x27;t have any \n, you&#x27;d just have an array of lines (without linefeeds), same as if you were reading lines from a file one at a time or splitting a binary on \n.<p>The other results that differ across engines seem to be because people either don&#x27;t understand regex or because the POSIX description of how to deal with such an input and config was ill-defined.
cpeterso大约 1 年前
$ is the regex’s “the buck stops here” symbol. Here at the end of the line. :)
AtNightWeCode大约 1 年前
There are many differences between implementations of regex. To name a few. Lookbehind, atomic groups, named capturing groups, recursion, timeouts and my favorite interop problem, unicode.
Izmaki大约 1 年前
The new-line character is an actual character &quot;at the end&quot; of the string though so it makes sense that $ would include the new-line character in multi-line matching.
评论 #39764116 未加载
评论 #39764113 未加载
wodenokoto大约 1 年前
&gt; So if you&#x27;re trying to match a string without a newline at the end, you can&#x27;t only use $ in Python! My expectation was having multiline mode disabled wouldn&#x27;t have had this newline-matching behavior, but that isn&#x27;t the case.<p>A reproducible example would be nice. I don’t understand what it is he cannot do. `re.search(&#x27;$&#x27;, &#x27;no new lines&#x27;)` returns a match.
评论 #39764753 未加载
febeling大约 1 年前
Seriously, just write one unit test for your regex.
评论 #39765987 未加载
silent_cal大约 1 年前
I think there&#x27;s a big opportunity to re-write Regex as a SQL-type language. It&#x27;s too bad I don&#x27;t feel like trying.
评论 #39773286 未加载
nurtbo大约 1 年前
Totally get the desire, but also feels like last two paragraphs are solvable with<p>``` re.match(text).extract().rstrip(“\n”) ```
croes大约 1 年前
Isn&#x27;t a string with a newline character automatically multiline?<p>The new line is just empty but not the first line anymore.
评论 #39764660 未加载
menacingly大约 1 年前
Of course it’s line. How could it be the end of the string when the matter at hand is defining the string?
ary大约 1 年前
Was any regex documentation unclear on this? Some libraries have modes that change the semantics of ^ and $ but I’ve always found their use to be rather clear. It’s the grouping and look ahead&#x2F;behind modifiers that I’ve always found hard to understand (at times).
评论 #39773250 未加载
nunez大约 1 年前
You can also use (?m) to enable multiline processing on PCRE-compatible regexp engines.
mdavid626大约 1 年前
Is this a bug?
humanlity大约 1 年前
Interesting
user2342大约 1 年前
I&#x27;m confused by this blog-post. In the table: what is the reg-ex pattern tested and against which input?
评论 #39764103 未加载
raldi大约 1 年前
Cmd-F perl<p><i>no matches</i>
1letterunixname大约 1 年前
Ugh. Whenever I hear people talk about regular expressions as a singular language or standard, I die a little inside.<p>PSA: Regex security is particular to each implementation flavor. Please know the nuances of a particular kind and be unambiguously precise.
k3vinw大约 1 年前
Another poor soul trying to solve one problem using regex and now they have two… ;)
callwhendone大约 1 年前
it&#x27;s end of line right?
michaelcampbell大约 1 年前
...IN PYTHON
teknopaul大约 1 年前
Tldr;<p>$ does not mean end of string in Python.