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

科技回声

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

GitHubTwitter

首页

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

资源链接

HackerNews API原版 HackerNewsNext.js

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

Things I Wish I'd Known About Bash

781 点作者 zwischenzug超过 7 年前

47 条评论

jordigh超过 7 年前
Using readline is a great thing to know about too.<p>My favourite little-known readline command is operate-and-get-next:<p><a href="https:&#x2F;&#x2F;www.gnu.org&#x2F;software&#x2F;bash&#x2F;manual&#x2F;html_node&#x2F;Miscellaneous-Commands.html" rel="nofollow">https:&#x2F;&#x2F;www.gnu.org&#x2F;software&#x2F;bash&#x2F;manual&#x2F;html_node&#x2F;Miscellan...</a><p>You can use it to search back in history with C-r and then execute that command with C-o and keep pressing C-o to execute the commands that followed that one in history. Very helpful for executing a whole block of history.<p>For some reason, this documentation is hard to find! It&#x27;s not here, for example:<p><a href="http:&#x2F;&#x2F;readline.kablamo.org&#x2F;emacs.html" rel="nofollow">http:&#x2F;&#x2F;readline.kablamo.org&#x2F;emacs.html</a><p>I&#x27;m a bit saddened when readline replacements don&#x27;t implement C-o. For example, the Python REPLs don&#x27;t have it.
评论 #16086646 未加载
评论 #16088750 未加载
评论 #16086912 未加载
评论 #16091022 未加载
sethrin超过 7 年前
I wrote a book on Bash too. The most important thing for anyone to know about Bash is that it&#x27;s intended as a command language, not a general purpose scripting language. If it&#x27;s longer than 10 lines, or if it uses two or more variables, you should probably have written it in something other than Bash.
评论 #16086191 未加载
评论 #16087099 未加载
评论 #16087897 未加载
评论 #16087832 未加载
评论 #16085888 未加载
评论 #16087157 未加载
评论 #16085836 未加载
joshbaptiste超过 7 年前
Hang out in #bash on IRC Freenode and you will be a Bash jedi <a href="http:&#x2F;&#x2F;mywiki.wooledge.org&#x2F;BashFAQ" rel="nofollow">http:&#x2F;&#x2F;mywiki.wooledge.org&#x2F;BashFAQ</a> best resource IMO for quick Bash syntax lookups as I always need to refer to the BashFaq to remember parameter expansion sub-string retrieval.<p><pre><code> parameter result ----------- ------------------------------ $name polish.ostrich.racing.champion ${name#*.} ostrich.racing.champion ${name##*.} champion ${name%%.*} polish ${name%.*} polish.ostrich.racing</code></pre>
评论 #16087829 未加载
评论 #16085737 未加载
unixthrowaway50超过 7 年前
The sections on quoting and globbing suggest this author, though obviously trying to be helpful, isn&#x27;t really knowledgeable enough to be writing such a guide.<p>I suggest reading this instead: <a href="http:&#x2F;&#x2F;www.grymoire.com&#x2F;Unix&#x2F;Sh.html" rel="nofollow">http:&#x2F;&#x2F;www.grymoire.com&#x2F;Unix&#x2F;Sh.html</a><p>Granted, it&#x27;s about the Bourne shell, but since Bash, Korn, and every standard UNIX shell is supposed to be compatible with it, it&#x27;s well worth learning.<p>And IMO, if you need more than what the Bourne shell provides, you should be using a proper programming language like Python instead.
amelius超过 7 年前
Bash has a huge number of little shortcuts that are difficult to learn. When one encounters a sequence of symbols like $(...), it is difficult to Google for its meaning. The reason shells nevertheless have these shortcuts is of course because they <i>are</i> shells: from the commandline it can be very convenient to use shortcuts.<p>But, in my opinion, that&#x27;s where it should stop: one shouldn&#x27;t use a shell language for scripting. In scripts, it is simpler to use more verbose and clear constructs, because most editors are very powerful and provide shortcuts themselves.
评论 #16085654 未加载
评论 #16086415 未加载
评论 #16085863 未加载
评论 #16088270 未加载
chriswarbo超过 7 年前
For me, the biggest gotcha in bash is whether or not a sub-process&#x2F;shell will be invoked, which can affect things like mutable variables and the number of open file handles. For example:<p><pre><code> COUNT=0 someCommand | while read -r LINE do COUNT=$(( COUNT + 1 )) done echo &quot;$COUNT&quot; </code></pre> This will always print `0`, since the `COUNT=` line will be run in a sub-process due to the pipe, and hence it can&#x27;t mutate the outer-process&#x27;s `COUNT` variable. The following will count as expected, since the `&lt;()` causes `someCommand` to run in a sub-process instead:<p><pre><code> COUNT=0 while read -r LINE do COUNT=$(( COUNT + 1 )) done &lt; &lt;(someCommand) echo &quot;$COUNT&quot; </code></pre> Another issue I ran into is `$()` exit codes being ignored when spliced into strings. For example, if `someCommand` errors-out then so will this:<p><pre><code> set -e FOO=$(someCommand) BAR=&quot;pre $FOO post&quot; </code></pre> Yet this will fail silently:<p><pre><code> set -e BAR=&quot;pre $(someCommand) post&quot;</code></pre>
评论 #16088474 未加载
评论 #16088200 未加载
评论 #16088781 未加载
lvillani超过 7 年前
shellcheck (<a href="https:&#x2F;&#x2F;www.shellcheck.net" rel="nofollow">https:&#x2F;&#x2F;www.shellcheck.net</a>) is an absolute godsend when writing Bash&#x2F;POSIX sh scripts.<p>It catches so many errors that I think it&#x27;s a must have in every programmer&#x27;s toolbox. It even catches bash-isms when you are targeting POSIX sh. It saved me many many hours of grief trying to debug shell scripts I wrote and changed the way I write them for the better.
评论 #16086482 未加载
评论 #16087453 未加载
评论 #16086839 未加载
tomxor超过 7 年前
<p><pre><code> `` vs $() </code></pre> I really appreciate authors who attack ambiguity or non-obvious equivalence in a subject head on. It&#x27;s one of those aspects of explaining that takes to heart the perspective of the learner.<p>Another recent example I encountered is from the online book <a href="http:&#x2F;&#x2F;neuralnetworksanddeeplearning.com" rel="nofollow">http:&#x2F;&#x2F;neuralnetworksanddeeplearning.com</a>, there are some confusing ambiguities and plain misleading contradictions in NN terminologies, one being: multi-layer perceptions do not use perception neurons, these things can really screw with you while you&#x27;re learning, especially the more subtle ones.<p>Some authors seem to have the ability to have full empathy for the novice while retaining expert knowledge and deep understanding by being able to both predict and answer relevant questions at the right point in an explanation at the right level of detail.
jwilk超过 7 年前
<p><pre><code> rename -n &#x27;s&#x2F;(.*)&#x2F;new$1$2&#x2F;&#x27; * </code></pre> There&#x27;s a chance this won&#x27;t work on your system.<p>There are two incompatible versions of rename in the wild:<p>1) Perl one: <a href="https:&#x2F;&#x2F;metacpan.org&#x2F;pod&#x2F;distribution&#x2F;File-Rename&#x2F;rename.PL" rel="nofollow">https:&#x2F;&#x2F;metacpan.org&#x2F;pod&#x2F;distribution&#x2F;File-Rename&#x2F;rename.PL</a><p>2) from util linux: <a href="http:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man1&#x2F;rename.1.html" rel="nofollow">http:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man1&#x2F;rename.1.html</a><p>Debian (and dertivaties) ship the former; other Linux distros likely the latter.
评论 #16086247 未加载
dorfsmay超过 7 年前
Two important things missing:<p>1) This is a huge pet peeve of mine, but it kills me when my coworkers &quot;bash&quot; emacs and sing the praise of vim, then proceed to explain to me that ctrl-R in bash searches for the last command with a given pattern. They also often refuse to believe me that they&#x27;re basically using emacs controls (because you know emacs&#x27; dirty). So, please, if you&#x27;re in love with vim and use ksh or bash, learn about &quot;set -o vi&quot;. Oh, and stop preaching!<p>2) &quot;help xxx&quot; for any xxx bash functionality, right there from the command line!
评论 #16085960 未加载
Sir_Cmpwn超过 7 年前
#0: If you&#x27;re writing scripts that are destined for other users, use POSIX sh instead.
评论 #16088132 未加载
评论 #16085925 未加载
评论 #16085825 未加载
评论 #16085449 未加载
jwilk超过 7 年前
<p><pre><code> $ grep somestring file1 &gt; &#x2F;tmp&#x2F;a $ grep somestring file2 &gt; &#x2F;tmp&#x2F;b $ diff &#x2F;tmp&#x2F;a &#x2F;tmp&#x2F;b </code></pre> You shouldn&#x27;t do that, but not because it&#x27;s not neat enough. &#x2F;tmp is world-writable, so you might be writing to somebody else&#x27;s file, or over a symlink that was set up by someone else. Use mktemp¹ for creating temporary files.<p>¹ <a href="http:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man1&#x2F;mktemp.1.html" rel="nofollow">http:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man1&#x2F;mktemp.1.html</a>
评论 #16087118 未加载
jwilk超过 7 年前
&gt; if [ x$(grep not_there &#x2F;dev&#x2F;null) = &#x27;x&#x27; ]<p>This is still wrong if the command can output spaces or meta-characters. You should quote the left operand, and then you don&#x27;t need to prepend x:<p>if [ &quot;$(grep not_there &#x2F;dev&#x2F;null)&quot; = &#x27;&#x27; ]
评论 #16086196 未加载
评论 #16086322 未加载
评论 #16086903 未加载
y7超过 7 年前
The author mentions the substitution !:1-$ to insert all the arguments from the last command (like !$ substitutes the last argument and !! the full command). Note that !* does exactly the same thing, which is a bit easier to type&#x2F;remember.
Nimitz14超过 7 年前
..it&#x27;d be nice if what was actually happening was explained of just statements like &quot;[ is the original form for tests, and then [[ was introduced, which is more flexible and intuitive&quot;
评论 #16085810 未加载
评论 #16085802 未加载
luckydude超过 7 年前
+1 for the parts that are portable to Bourne shell&#x2F;ksh&#x2F;zsh.<p>-1000 for the parts that are specific to Bash. Stuff like that has been huge pain in my ass over the years. Some clever programmer uses some bash-ism and the build breaks on some ancient hardware that doesn&#x27;t have bash.<p>I realize my complaint sounds like Henry Spencer&#x27;s Ten Commandments and perhaps it feels outdated but trust me, you don&#x27;t want to wade into thousands of lines of shell to track down why something doesn&#x27;t work on the stupid AIX box.
评论 #16085890 未加载
评论 #16085773 未加载
teddyh超过 7 年前
If you use a thing a lot, you should probably invest some time in reading the manual for it.<p>The manual for bash consists of its Unix-style &quot;man&quot; page, and is therefore more of a reference than an instruction manual. I suggest using the <i>Advanced Bash-Scripting Guide</i> (<a href="http:&#x2F;&#x2F;tldp.org&#x2F;guides.html#abs" rel="nofollow">http:&#x2F;&#x2F;tldp.org&#x2F;guides.html#abs</a>).
jorams超过 7 年前
I really wonder why the author didn&#x27;t just leave off the first two, and call it &quot;Eight Things I...&quot;. Starting off with &quot;backslash escapes can be confusing&quot; and &quot;&#x2F;* doesn&#x27;t just match things consisting of 0 or more slashes!&quot; makes no sense if you&#x27;re later going to skip over !! because it&#x27;s &quot;obvious&quot;.
Exuma超过 7 年前
This is the most helpful bash diagram ever... why didn&#x27;t I search for this before! <a href="https:&#x2F;&#x2F;zwischenzugs.files.wordpress.com&#x2F;2018&#x2F;01&#x2F;shell-startup-actual.png" rel="nofollow">https:&#x2F;&#x2F;zwischenzugs.files.wordpress.com&#x2F;2018&#x2F;01&#x2F;shell-start...</a>
评论 #16086406 未加载
wodenokoto超过 7 年前
What was the surprising part about<p><pre><code> echo &#x27;*&#x27; echo &quot;*&quot; </code></pre> ? Both prints an asterisk. Is &#x27;*&#x27; some sort of BASH variable?
评论 #16087162 未加载
earenndil超过 7 年前
<p><pre><code> if [ x$(grep not_there &#x2F;dev&#x2F;null) = &#x27;x&#x27; ] </code></pre> See now, I never get why people do this. -z has existed forever.
评论 #16091945 未加载
seanwilson超过 7 年前
&gt; !$ - I use this dozens of times a day. It repeats the last argument of the last command.<p>Press ESC then full stop instead. Less key presses.
评论 #16087647 未加载
JepZ超过 7 年前
One of my favorite Bash patterns is the following. I call it &#x27;feed the fish&#x27;:<p><pre><code> . &lt;(curl https:&#x2F;&#x2F;example.com&#x2F;trusted.sh) </code></pre> While it is <i>extremely dangerous</i> I found it so easy to remember, that it stuck in my head. It downloads the script and executes it in the current shell. So if anything unexpected happens you probably have a real problem ;-)<p>Background: A few years ago I was writing a Bash based OS installer. So after booting from a live CD I had to fetch the installer and execute it, which lead me to using that pattern frequently.<p>While I love it, I can&#x27;t stress enough how dangerous it is.
martincmartin超过 7 年前
If you &quot;set -e&quot;, you probably also want to &quot;set pipefail&quot;. By default, a pipeline returns the return value of the last element. pipefail means that if any element of the pipeline fails, then the pipeline as a whole will fail. I discovered this the hard way when I had:<p>make run-asan-test | c++filt<p>And even if the tests failed, the script would succeed.
mlinksva超过 7 年前
re 9) I feel better about always feeling at least slightly confused about what files are being sourced.<p>The graph included seems to originate from <a href="https:&#x2F;&#x2F;blog.flowblok.id.au&#x2F;2013-02&#x2F;shell-startup-scripts.html" rel="nofollow">https:&#x2F;&#x2F;blog.flowblok.id.au&#x2F;2013-02&#x2F;shell-startup-scripts.ht...</a>
评论 #16089001 未加载
hiisukun超过 7 年前
I didn&#x27;t see it mentioned, but I use it frequently so here is my tip. I&#x27;m not sure if it is bash specific (I just use it!).<p>Instead of typing !$ for the previous command&#x27;s final argument, you can use the keyboard shortcut alt+. (alt+period). Pressing it multiple times will go to the last argument of previous commands. I use this quite a bit and found it easier than !$, because you can see which command it will be : )<p>I still don&#x27;t always understand exactly what is happening with subprocesses vs subshells (chriswarbo&#x27;s post is very useful in pointing out how wrinkly this can be), so I try and keep bash my usage simple.
aplorbust超过 7 年前
Blog states that author has 20 years of development experience.<p>Blog post suggests he knew little of basic shell scripting until recently.<p>Blog also reveals he is selling a book on shell scripting with Bash, &quot;Learn Bash the Hard Way.&quot;
评论 #16088497 未加载
gumby超过 7 年前
If you want all the args to the previous (or earlier) command just use !<i>. (e.g. a common idiom for me is cat `!</i>`). Or you tried a git mv out of habit but the dir isn’t being managed by git: !gi:<i>
评论 #16087608 未加载
BeetleB超过 7 年前
This is why I use xonsh (<a href="http:&#x2F;&#x2F;xon.sh" rel="nofollow">http:&#x2F;&#x2F;xon.sh</a>). It lets me use Python as a shell, and I don&#x27;t have to remember too much awkward syntax.
brianlund超过 7 年前
I wasted a lot of time on this one:<p>If you declare a local variable and set it in the same step e.g: local MYVAR = $(&#x2F;bin&#x2F;false) The return code you get is from the local declaration, not assigning a value to the variable. It can be quite confusing when you afterwards check the return code with $? and it returns 0. Avoid it by assigning the value in a seperate command.
walshemj超过 7 年前
Interesting but from a modern perspective is not perl a better scripting language to learn.<p>I have never used bash scripts professionally i.e. as a language rather than a simple script with just a command in.<p>Like wise back in 87 or so I got trained in sed and I have only used it once since, and that was when I was playing around with early linix&#x27;s (when it came on a huge number of floppys)
评论 #16086992 未加载
kerny超过 7 年前
9) The remote bash startup order is further complicated by the existence of a compile time flag SSH_SOURCE_BASHRC. This flag determines if a remote non-interactive shell will load the ~&#x2F;.bashrc file.<p>This flag is turned off by default and stays off in some distributions (like Archlinux), but is turned on in others (Debian, Fedora, ...) to replicate very old rsh behaviour.
saagarjha超过 7 年前
I&#x27;ve been looking for something like &lt;() for a long time. Thanks for sharing it!<p>Regarding :h, is it any different than just using dirname?
indigodaddy超过 7 年前
Can someone explain :h as the article&#x27;s description was not clear at all to me what was going on there.
评论 #16085829 未加载
评论 #16085720 未加载
评论 #16088121 未加载
评论 #16085568 未加载
i_feel_great超过 7 年前
What is the best alternatives to bash for writing fairly large automation scripts? I have already looked at Python, Lua and Guile. The last two especially since I like using them and they have some sort of posix interfaces. I haven&#x27;t looked at Perl 6.
评论 #16088271 未加载
mehrdadn超过 7 年前
The trickiest part of Bash I know is that &quot;$(command)&quot; results in the truncation of the output of the command before the newline. It&#x27;s both handy and damning depending on what you&#x27;re trying to do.
评论 #16088618 未加载
emmelaich超过 7 年前
I haven&#x27;t used the ! history for many years. It&#x27;s simply easier and faster to use command line editing.<p>! was useful before command line editing; but not much since.
thibran超过 7 年前
Does fish-shell have an equivalent for &#x27;&lt;()&#x27;?
评论 #16085521 未加载
luord超过 7 年前
I didn&#x27;t know a few of these, and I think I&#x27;ll find `&lt;()` specially useful.
wand3r超过 7 年前
I understand &quot;the hard way&quot; is a commonly used phrase but it does seem a bit infringing on Zed Shaw&#x27;s entire series Learn Code the Hard Way. Easily confusing. Other than that, good work
ausjke超过 7 年前
bash or its minimal version such as ash is critical for embedded systems where python&#x2F;perl etc are too fat.
zbentley超过 7 年前
The thing I wished I had learned earlier is &quot;quick and dirty assertions&quot;. If you write lots of functions in Bash, you quickly end up getting tripped up by cases where an argument is omitted and the function does something totally batshit given the missing (empty string) argument. Now, the canonical way to handle this is to put validators on your input, (and make sure those validators don&#x27;t crash with cryptic errors if someone calling your function is using &quot;set -u&quot;) like so:<p><pre><code> function() myfunc { local foo=&quot;${1:-}&quot; if [ -z &quot;$foo&quot; ]; then echo &quot;Invalid first parameter!&quot; &gt;&amp;2 return 127 fi ... } </code></pre> ...but <i>man</i>, that&#x27;s time consuming when you have lots of parameters.<p>Instead, the quick and dirty way is to just &quot;assert&quot; via [parameter expansion](<a href="https:&#x2F;&#x2F;www.gnu.org&#x2F;software&#x2F;bash&#x2F;manual&#x2F;html_node&#x2F;Shell-Parameter-Expansion.html" rel="nofollow">https:&#x2F;&#x2F;www.gnu.org&#x2F;software&#x2F;bash&#x2F;manual&#x2F;html_node&#x2F;Shell-Par...</a>):<p><pre><code> function myfunc() { local foo=&quot;${1:?First parameter must be provided}&quot; ... } </code></pre> Much quicker, especially when throwing things together in a hurry. It has a gotcha, though: &quot;:?&quot; assertion doesn&#x27;t cause a function to return early, it <i>shuts down the whole interpreter</i> after outputting the error. So it&#x27;s more like a true assert() statement than an input validator. If you&#x27;d only ever call your function in a subshell, this won&#x27;t matter (because the subshell will exit early with a nonzero code, big deal), but otherwise it can be a nasty surprise to users when an argument-validation issue inside a function shuts the program down. Then again, the &quot;return 127&quot; in the first example would also shut the program down if someone was using &quot;set -e&quot;.<p>...and while we&#x27;re on the subject of &quot;set -e&quot;, I think that the [&quot;unofficial Bash strict mode&quot;](<a href="http:&#x2F;&#x2F;redsymbol.net&#x2F;articles&#x2F;unofficial-bash-strict-mode&#x2F;" rel="nofollow">http:&#x2F;&#x2F;redsymbol.net&#x2F;articles&#x2F;unofficial-bash-strict-mode&#x2F;</a>) (putting &quot;set -euo pipefail&quot; and &quot;IFS=$&#x27;\n\t&#x27;&quot; at the top of your scripts) has been a bigger bug-prevention&#x2F;rapid development aide to me than anything else. To be clear, I think it&#x27;s a means of detecting <i>some</i> kinds of bugs. I&#x27;ve read Wooledge and others&#x27; objections to those patterns, especially &quot;set -e&quot;, and agree with the point that this does not make your programs <i>objectively safer</i> and shouldn&#x27;t be counted on as a crutch. Then again, neither does a linter, but it still helps you detect and avoid some kinds of bugs, so why not use it?
评论 #16091888 未加载
meow_mix超过 7 年前
It&#x27;s 2018 and we&#x27;re still talking about writing non-trivial bash scripts?
评论 #16089855 未加载
zbentley超过 7 年前
Something I wish people teaching intermediate or advanced Bash tricks would emphasize more is how to make your program compatible with other shells. With the rise of Zsh&#x27;s popularity, and the switch to Dash for Ubuntu&#x2F;some Debian derivatives, I see a lot of people repeating bashisms in code they share without the knowledge that a) their code may not work for an unexpectedly large number of people, and b) switching to compatible equivalents doesn&#x27;t make their code worse or less performant in many&#x2F;most cases.<p>The most common bashisms and ways to avoid them are:<p>- Double brackets ([[) around conditions. Yes, I know that [ is a program (don&#x27;t believe me? &quot;which [&quot;). That doesn&#x27;t mean Bash uses it; it uses a builtin which is (almost) equivalent to [[ instead. Use that and your code will work in zsh&#x2F;dash&#x2F;all other POSIX shells. And while you&#x27;re at it, stop using &quot;which&quot; as an authority for &quot;is this a shell builtin or not?&quot; [type()](<a href="http:&#x2F;&#x2F;linuxcommand.org&#x2F;lc3_man_pages&#x2F;typeh.html" rel="nofollow">http:&#x2F;&#x2F;linuxcommand.org&#x2F;lc3_man_pages&#x2F;typeh.html</a>) is your friend.<p>- When comparing strings for equality, use a single equals sign &quot;=&quot;, not &quot;==&quot; (e.g. &#x27;if [ &quot;$foo&quot; = &quot;some string&quot; ]&#x27;). I know it feels dirty if you&#x27;ve programmed in any other language, but it changes nothing about your code&#x27;s behavior and makes it compatible with several other shells.<p>- Don&#x27;t use &quot;function funcname()&quot; syntax. It adds nothing over the basic &quot;funcname()&quot; syntax, but prevents your code running in many&#x2F;most non-Bash shells. And consider putting your function-opening brace on a separate line (someone once told me that there are shells that won&#x27;t accept any other function declaration style, but I&#x27;ve never seen one, so ymmv).<p>- Don&#x27;t use &quot;local&quot; if you need to interoperate with ksh. Abandoning &quot;local&quot; pollutes global namespaces, though, so your call.<p>- Don&#x27;t use substring expansion (e.g. extracting the 3rd-10th characters of a string via &#x27;substr=&quot;${somevar:3:7}&quot;&#x27;. That&#x27;s not supported in many other shells. Alternatives include sed&#x2F;awk&#x2F;etc., or, if invoking external programs is absolutely unacceptable to you, something horrific like:<p><pre><code> substr() { local input=&quot;${1:?String is required}&quot; local dist_from_start=&quot;${2:?Start position is required}&quot; local dist_from_end=&quot;${3:-${#input}}&quot; # Here, it&#x27;s actually &#x27;offset&#x27;, not distance. local start_nulls= local end_nulls= dist_from_end=$(( 5 * (${#input} - ($dist_from_start + $dist_from_end)) )) dist_from_start=$(( 5 * $dist_from_start )) # Make a string of the regex for &quot;any not null character&quot; that &quot;masks&quot; the # characters in the input before the start point, and the characters after # the end of the substring. This is disgusting, and is only done because the # parameter expansion statements can&#x27;t contain repetitions (e.g. [^\0]{5}) # without the bash-only &#x27;extglob&#x27; shell option. # The not-null character is used because it will never match in a shell # string. while true; do if [ &quot;${#start_nulls}&quot; -lt $dist_from_start ]; then start_nulls=&quot;${start_nulls}[^\0]&quot; elif [ &quot;${#end_nulls}&quot; -lt $dist_from_end ]; then end_nulls=&quot;${end_nulls}[^\0]&quot; else break fi done input=&quot;${input#$start_nulls}&quot; echo &quot;${input%$end_nulls}&quot; } substr &quot;$@&quot; </code></pre> ...actually, please never use that code. Ew.<p>Anyway, some more bashisms: <a href="https:&#x2F;&#x2F;mywiki.wooledge.org&#x2F;Bashism" rel="nofollow">https:&#x2F;&#x2F;mywiki.wooledge.org&#x2F;Bashism</a>
tzahola超过 7 年前
My take on the same topic:<p>- use the unofficial strict mode: <a href="http:&#x2F;&#x2F;redsymbol.net&#x2F;articles&#x2F;unofficial-bash-strict-mode&#x2F;" rel="nofollow">http:&#x2F;&#x2F;redsymbol.net&#x2F;articles&#x2F;unofficial-bash-strict-mode&#x2F;</a><p>- use parameter substitutions like ${foo#prefix}, ${foo%suffix} instead of invoking sed&#x2F;awk<p>- process substitution instead of named pipes: &lt;(), &gt;()<p>- know the difference between an inline group {} and a subshell ()<p>- use printf &quot;%q&quot; when passing variables to another shell (e.g. assembling a command locally and executing it via SSH)
评论 #16087127 未加载
评论 #16087093 未加载
carapace超过 7 年前
Damn it this boils down to RTFM, specifically the bash man page.
评论 #16086308 未加载
clishem超过 7 年前
You shouldn&#x27;t call your book &#x27;learn X the hard way&#x27; if it isn&#x27;t (also) freely available online if you ask me.