From owner-freebsd-questions@freebsd.org Fri Feb 12 19:26:24 2016 Return-Path: Delivered-To: freebsd-questions@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 1CE8CAA6736 for ; Fri, 12 Feb 2016 19:26:24 +0000 (UTC) (envelope-from me@janh.de) Received: from mout.kundenserver.de (mout.kundenserver.de [217.72.192.74]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mout.kundenserver.de", Issuer "TeleSec ServerPass DE-2" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 8CC9D1A3A for ; Fri, 12 Feb 2016 19:26:22 +0000 (UTC) (envelope-from me@janh.de) Received: from [192.168.178.20] ([87.174.219.28]) by mrelayeu.kundenserver.de (mreue101) with ESMTPSA (Nemesis) id 0LvSJX-1a3oN21lg3-010gan; Fri, 12 Feb 2016 20:20:39 +0100 Subject: Re: /bin/sh starts with check in script To: Ian Smith References: <20160213034617.D51785@sola.nimnet.asn.au> Cc: Sergei G , freebsd-questions@freebsd.org From: Jan Henrik Sylvester X-Enigmail-Draft-Status: N1110 Message-ID: <56BE3085.9040505@janh.de> Date: Fri, 12 Feb 2016 20:20:37 +0100 User-Agent: Mozilla/5.0 (X11; FreeBSD amd64; rv:38.0) Gecko/20100101 Thunderbird/38.5.0 MIME-Version: 1.0 In-Reply-To: <20160213034617.D51785@sola.nimnet.asn.au> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 7bit X-Provags-ID: V03:K0:/4paaWuUAnRd0IQEttjzuftG9uAelYk04eodCzKQZyKJZKcVj04 wAZBsAKgdRgmupply83HzH1sAyUygKGJ6Acq5R3YQChD17JQzTTqHm1vQrthxziPFgwkbGr F3Zcmup0Znyyi3xCO6t3b8jcPbAR+/X5O7K2J+a4ZCm95WNYbEwr1CqIGDf2YCB6KzK9dLu 4sCD4rfyclvVJY7jm8KDQ== X-UI-Out-Filterresults: notjunk:1;V01:K0:bVrfOcY1Pjc=:Wz94RPd1b46RJgjNMGAWBc KrMTloVb9K3Yn7v4uq/n+Ngxjfh4Csfqm/2SF/Ie+6MOv/WhVZeqpai1orR6VETWZFvaaCMHI 2BUH2cq+8/FhnuT32qM8GhCPFHEICW8DDve3scAgaaKCwzShlWLCF4lZsu7GhGkYKbyeAZNl4 DXVt3746nCV5wzq3CxDbWb8P6AX+XTBBcLzgr4MT1aB6wieBb+cIMnD0AKI/asYljLhACcW5U gqUCjKZtOovEO7CuwfMujTbuAh/7LUAs6LSkEJIaB8tT8K6tKhA+08AaSwfzSKXQgc1RKR1t6 uX6M5UVwRAXm33qoshYaBaTTuvbLwDuKESR3y6v2YhFD21RdPWHn7r5MAFj+2os46qUhQUFgD zQQPsfDNiRrBDRVo2/BrsDTy2t9Lbgo030+jbI925e6smmE/vpfKYaMn2nat76np+1iGpVpOI rCn2Yji2+doGCiYDmpDVrWsYbsd6VCG8jRJYxhfSEe8nlRW9raf+1inMphnELb1tq7gpSByPy nRxFEz1llbNiblIRg8uIYnwKMOkjq/xuYfrou6NXBo51aazYThpGHX32vDYW/6IZ5nCurWl9K lcBa+9aYCy4U0eDin5s+FRVIUbhMQMImYiCo5wezgl0FkawLZ+0UTiwplTaiby4QK9YFMCEfR jgeJGCggFjxDhSHEEcC/ZJlxw8WhwQohy2WDgM7hgVdGwxgwbeX8rwXC3fAds/Zzec/Yt3u0e c3+KzIKQsR8RHccV X-BeenThere: freebsd-questions@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: User questions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 12 Feb 2016 19:26:24 -0000 On 02/12/2016 18:53, Ian Smith wrote: > In freebsd-questions Digest, Vol 610, Issue 5, Message: 1 > On Thu, 11 Feb 2016 15:29:22 +0100 Jan Henrik Sylvester wrote: > > On 02/10/2016 13:58, Sergei G wrote: > > > I came up with this solution to check if variable $line starts with a > > > hash. Basically I am checking if line is a comment in the configuration > > > file. > > > > > > #!/bin/sh > > > if expr "${line}" : '#.*' > /dev/null; then > > > echo Ignoring comment line > > > fi > > expr(1) suggests preferring sh(1) for maths expressions and parsing :) > > > > I had to redirect to /dev/null, because expr prints a number to STDOUT. > > > Is there a better way to do this kind of string matching check in > > > /bin/sh (not bash)? > > > > [ "${line#\#}" != "$line" ] && echo comment > > > > See the Parameter Expansion section of sh(1). > > That looks like it ought to work, but does not here on stable/9; I don't > think it honours the escaping when expecting a second '#' or other char? I am rather curious about this, because I have been using something like "${line#'#'}" for a long time, but wanted to save a character here. I just extracted kernel and base from a 9.3-RELEASE image to a directory and did a chroot into it, started sh there and tried: line='#COMMENT' [ "${line#\#}" != "$line" ] && echo comment It worked. I lack the time to set up a proper VM with 9/stable, but I would not think the kernel mattered. Are you sure it does not work there? What does A='#C' ; echo "${A#\#}" "${A#'#'}" give on stable/9? > After some playing, this also finds comment lines that have optional > whitespace before the first '#', not pinning comments only to column 1, > while ignoring comments after other text. Not what everybody needs .. > > [ ! "`echo ${line%%#*} | tr -d [:blank:]`" ] && echo comment > > BUG|FEATURE: if $line is the null string it is taken to be a comment. If you have that in a loop for every line in a long file, the process spawning might take a lot of time. Why not use grep(1), if you do not care to spawn a process? Of course, you should call grep(1) once first and then process every line from the output. Without spawning a process, you might do the same assuming you have not changed IFS: line=${line%%#*} ; [ "$line" = "${line%%[!$IFS]*}" ] && echo comment Or you do TAB=$(printf '\t') in the beginning and use: line=${line%%#*} ; [ "$line" = "${line%%[! $TAB]*}" ] && echo comment String processing in sh(1) is so much fun... if you want to secure your job with elegant use of obscurity, you can strip the leading blanks first and then check for the first character directly: line=${line#"${line%%[! $TAB]*}"} [ "${line%"${line#?}"}" = "#" ] && echo 'line starts with #' For boring readability you go more along Matthew's solution using case or you do spawn one grep(1) process. Cheers, Jan Henrik