TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

Bash patterns I use weekly

278 pointsby gcmeplzover 3 years ago

22 comments

jphover 3 years ago
&gt; git bisect is the &quot;real&quot; way to do this, but it&#x27;s not something I&#x27;ve ever needed<p>git bisect is great and worth trying; it does what you&#x27;re doing in your bash loop, plus faster and with more capabilities such as logging, visualizing, skipping, etc.<p>The syntax is: $ git bisect run &lt;command&gt; [arguments]<p><a href="https:&#x2F;&#x2F;git-scm.com&#x2F;docs&#x2F;git-bisect" rel="nofollow">https:&#x2F;&#x2F;git-scm.com&#x2F;docs&#x2F;git-bisect</a>
评论 #29319636 未加载
评论 #29345106 未加载
stewartbutlerover 3 years ago
I&#x27;ve always had trouble getting `for` loops to work predictably, so my common loop pattern is this:<p><pre><code> grep -l -r pattern &#x2F;path&#x2F;to&#x2F;files | while read x; do echo $x; done </code></pre> or the like.<p>This uses bash read to split the input line into words, then each word can be accessed in the loop with variable `$x`. Pipe friendly and doesn&#x27;t use a subshell so no unexpected scoping issues. It also doesn&#x27;t require futzing around with arrays or the like.<p>One place I <i>do</i> use bash for loops is when iterating over args, e.g. if you create a bash function:<p><pre><code> function my_func() { for arg; do echo $arg done } </code></pre> This&#x27;ll take a list of arguments and echo each on a separate line. Useful if you need a function that does some operation against a list of files, for example.<p>Also, bash expansions (<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>) can save you a ton of time for various common operations on variables.
评论 #29326784 未加载
评论 #29328598 未加载
评论 #29322365 未加载
评论 #29322382 未加载
michaelhoffmanover 3 years ago
I have something like this in my bashrc:<p><pre><code> preexec () { # shellcheck disable=2034 _CMD_START=&quot;$(date +%s)&quot; } trap &#x27;preexec; trap - DEBUG&#x27; DEBUG PROMPT_COMMAND=&quot;_CMD_STOP=\$(date +%s) let _CMD_ELAPSED=_CMD_STOP-_CMD_START if [ \$_CMD_ELAPSED -gt 5 ]; then _TIME_STR=\&quot; (\${_CMD_ELAPSED}s)\&quot; else _TIME_STR=&#x27;&#x27; fi; &quot; PS1=&quot;\n\u@\h \w\$_TIME_STR\n\\$ &quot; PROMPT_COMMAND+=&quot;trap &#x27;preexec; trap - DEBUG&#x27; DEBUG&quot; </code></pre> Whenever a command takes more than 5 s it tells me exactly how long at the next prompt.<p>I didn&#x27;t know about `$SECONDS` so I&#x27;m going to change it to use that.
评论 #29321231 未加载
评论 #29322013 未加载
caymanjimover 3 years ago
Installing GNU stuff with the &#x27;g&#x27; prefix (gsed instead of sed) means having to remember to include the &#x27;g&#x27; when you&#x27;re on a Mac and leave it off when you&#x27;re on Linux, or use aliases, or some other confusing and inconvenient thing, and then if you&#x27;re writing a script meant for multi-platform use, it still won&#x27;t work. I find it&#x27;s a much better idea to install the entire GNU suite without the &#x27;g&#x27; prefix and use PATH to control which is used. I use MacPorts to do this (&#x2F;opt&#x2F;local&#x2F;libexec&#x2F;gnubin), and even Homebrew finally supports this, although it does it in a stupid way that requires adding a PATH element for each individual GNU utility (e.g. &#x2F;usr&#x2F;local&#x2F;opt&#x2F;gnu-sed&#x2F;libexec&#x2F;gnubin).
R0flcopt3rover 3 years ago
You can use `wait` to wait for jobs to finish.<p><pre><code> some_command &amp; some_other_command &amp; wait</code></pre>
评论 #29320095 未加载
l0b0over 3 years ago
<p><pre><code> &gt; 1. Find and replace a pattern in a codebase with capture groups &gt; git grep -l pattern | xargs gsed -ri &#x27;s|pat(tern)|\1s are birds|g&#x27; </code></pre> Or, in IDEA, Ctrl-Shift-r, put &quot;pat(tern)&quot; in the first box and &quot;$1s are birds&quot; in the second box, Alt-a, boom. Infinitely easier to remember, and no chance of having to deal with any double escaping.
评论 #29328010 未加载
评论 #29323885 未加载
评论 #29322836 未加载
barbazooover 3 years ago
&gt; git bisect is the &quot;real&quot; way to do this, but it&#x27;s not something I&#x27;ve ever needed<p>uh, yeah, you did need it, that&#x27;s why you came up with &quot;2. Track down a commit when a command started failing&quot;. Seriously though, git bisect is really useful to track down that bug in O(log n) rather than O(n).
评论 #29323201 未加载
评论 #29321276 未加载
bloopernovaover 3 years ago
This thread seems like a good place to ask this:<p>When you&#x27;re running a script, what is the expected behaviour if you just run it with no arguments? I think it shouldn&#x27;t make any changes to your system, and it should print out a help message with common options. Is there anything else you expect a script to do?<p>Do you prefer a script that has a set of default assumptions about how it&#x27;s going to work? If you need to modify that, you pass in parameters.<p>Do you expect that a script will lay out the changes it&#x27;s about to make, then ask for confirmation? Or should it just get out of your way and do what it was written to do?<p>I&#x27;m asking all these fairly basic questions because I&#x27;m trying to put together a list of things everyone expects from a script. Not exactly patterns per se, more conventions or standard behaviours.
评论 #29321397 未加载
评论 #29320698 未加载
评论 #29321394 未加载
评论 #29351978 未加载
评论 #29321009 未加载
guruparan18over 3 years ago
I am confused how this works. I would assume `SECONDS` would just be a shell variable and it was first assigned `0` and then it should stay same, why did it keep counting the seconds?<p><pre><code> &gt; SECONDS bash: SECONDS: command not found &gt; SECONDS=0; sleep 5; echo $SECONDS; 5 &gt; echo &quot;Your command completed after $SECONDS seconds&quot;; Your command completed after 41 seconds &gt; echo &quot;Your command completed after $SECONDS seconds&quot;; Your command completed after 51 seconds &gt; echo &quot;Your command completed after $SECONDS seconds&quot;; Your command completed after 53 seconds</code></pre>
评论 #29320342 未加载
notatoadover 3 years ago
I really love this style of blog post. Short, practical, no backstory, and not trying to claim one correct way to do anything. Just an unopinionated share that was useful to the author.<p>It seems like a throwback to a previous time, but honestly can&#x27;t remember when that was. Maybe back to a time when I hoped this was what blogging could be.
marcodiegoover 3 years ago
We need a simpler regex format. One that allows easy searching and replacing in source code. Of course, some IDE&#x27;s already to that pretty well, but I&#x27;d like to be able to do it from the command line with a stand alone tool I can easily use in scripts.<p>The simplest thing I know that is able to do that is coccinelle, but even coccinelle is not handy enough.
评论 #29322941 未加载
评论 #29322592 未加载
js2over 3 years ago
My git-gsr (global search replace) command:<p><a href="https:&#x2F;&#x2F;gist.github.com&#x2F;jaysoffian&#x2F;0eda35a6a41f500ba5c458f02a29865d" rel="nofollow">https:&#x2F;&#x2F;gist.github.com&#x2F;jaysoffian&#x2F;0eda35a6a41f500ba5c458f02...</a><p>Uses perl instead of gsed, defaults to fixed strings but supports perl regexes, properly handles filenames with whitespace.
1vuio0pswjnm7over 3 years ago
To conserve host resources RFC 2616 recommends making multiple HTTP requests over a single TCP connection (&quot;HTTP&#x2F;1.1 pipelining&quot;).<p>The cURL project said it never properly suported HTTP&#x2F;1.1 pipelining and in 2019 it said it was removed once and for all.<p><a href="https:&#x2F;&#x2F;daniel.haxx.se&#x2F;blog&#x2F;2019&#x2F;04&#x2F;06&#x2F;curl-says-bye-bye-to-pipelining&#x2F;" rel="nofollow">https:&#x2F;&#x2F;daniel.haxx.se&#x2F;blog&#x2F;2019&#x2F;04&#x2F;06&#x2F;curl-says-bye-bye-to-...</a><p>Anyway, curl is not needed. One can write a small program in their language of choice to generate HTTP&#x2F;1.1, but even a simple shell script will work. Even more, we get easy control over SNI which curl binary does have have.<p>There are different and more concise ways, but below is an example, using the IFS technique.<p>This also shows the use of sed&#x27;s &quot;P&quot; and &quot;D&quot; commands (credit: Eric Pement&#x27;s sed one-liners).<p>Assumes valid, non-malicious URLs, all with same host.<p>Usage: 1.sh &lt; URLs.txt<p><pre><code> #!&#x2F;bin&#x2F;sh (IFS=&#x2F;;while read w x y z;do case $w in http:|https:);;*)exit;esac; case $x in &quot;&quot;);;*)exit;esac; echo $y &gt; .host printf &#x27;%s\r\n&#x27; &quot;GET &#x2F;$z HTTP&#x2F;1.1&quot;; printf &#x27;%s\r\n&#x27; &quot;Host: $y&quot;; # add more headers here if desired; printf &#x27;Connection: keep-alive\r\n\r\n&#x27;;done|sed &#x27;N;$!P;$!D;$d&#x27;; printf &#x27;Connection: close\r\n\r\n&#x27;; ) &gt;.http read x &lt; .host; # SNI; #openssl s_client -connect $x:443 -ign_eof -servername $x &lt; .http; # no SNI; openssl s_client -connect $x:443 -ign_eof -noservername &lt; .http; exec rm .host .http;</code></pre>
评论 #29327232 未加载
评论 #29326275 未加载
geocrasherover 3 years ago
I want to like this, but the for loop is unnecessarily messy, and not correct.<p><pre><code> for route in foo bar baz do curl localhost:8080&#x2F;$route done </code></pre> That&#x27;s just begging go wonky. Should be<p><pre><code> stuff=&quot;foo bar baz&quot; for route in $stuff; do echo curl localhost:8080&#x2F;$route done </code></pre> Some might say that it&#x27;s not absolutely necessary to abstract the array into a variable and that&#x27;s true, but it sure does make edits a lot easier. And, the original is missing a semicolon after the &#x27;do&#x27;.<p>I think it&#x27;s one reason I dislike lists like this- a newb might look at these and stuff them into their toolkit without really knowing why they don&#x27;t work. It slows down learning. Plus, faulty tooling can be unnecessarily destructive.
评论 #29320091 未加载
评论 #29323024 未加载
评论 #29320061 未加载
评论 #29320375 未加载
penguin_boozeover 3 years ago
If I find myself running a set of commands in parallel, I&#x27;d keep a cheap Makefile around: individual commands I want to run in parallel will be written as phony targets:<p><pre><code> all: cmd1 cmd2 cmd1: sleep 5 cmd2: sleep 10 </code></pre> And then<p><pre><code> make -j[n]</code></pre>
Hikikomoriover 3 years ago
My daily bash pattern.<p><pre><code> cat file cat file | grep something</code></pre>
评论 #29324799 未加载
评论 #29327101 未加载
评论 #29326963 未加载
ghostly_sover 3 years ago
Huh, never knew about $SECONDS.
usefulcatover 3 years ago
&gt; Use for to iterate over simple lists<p>I definitely use this all the time. Also, generating the list of things over which to iterate using the output of a command:<p><pre><code> for thing in $(cat file_with_one_thing_per_line) ; do ...</code></pre>
评论 #29321889 未加载
评论 #29322154 未加载
gnubisonover 3 years ago
It’s simple enough to use macos sed here instead of needing gsed: just use ‘-i &#x27;&#x27;’ instead of ‘-i’.
harvieover 3 years ago
curl localhost:8080&#x2F;{foo,bar,baz}
unixheroover 3 years ago
A lot of genious moves here I have never seen or thought of. Brilliant. Grabbing pids was mindblowingly effective.
Arch-TKover 3 years ago
This post and comments section means I no longer wonder why 99% of shell scripts I come across look inept. I&#x27;m sorry guys but seriously please actually learn bash (and ideally not from this blog post). There&#x27;s so many things wrong in the post and the comments that it&#x27;s difficult to enumerate.<p>To start with, if you ever feel the need to write a O(n) for loop for finding which commit broke your build, you DID need git-bisect.<p>Definitely DONT&#x27;T wait for PIDs like that and if you do want to write code like that, maybe actually use the arrays bash provides?<p>If your complaint is that for a in b c d; do ...; done is unclear, then maybe also use lists there, because what&#x27;s definitely LESS clear is putting things in a variable and relying on splitting.<p>And most importantly, DO quote things (except when it&#x27;s unnecessary).
评论 #29326071 未加载
评论 #29325828 未加载