Hot answers tagged

286

First, note that the -z test is explicitly for: the length of string is zero That is, a string containing only spaces should not be true under -z, because it has a non-zero length. What you want is to remove the spaces from the variable using the pattern replacement parameter expansion: [[ -z "${param// }" ]] This expands the param variable and ...


173

With bash 4.2 and above, you can do: ${var::-1} Example: $ a=123 $ echo "${a::-1}" 12 Notice that for older bash ( for example, bash 3.2.5 on OS X), you should leave spaces between and after colons: ${var: : -1}


165

My favorite way to do it is by using /dev/urandom together with tr to delete unwanted characters. For instance, to get only digits and letters: head /dev/urandom | tr -dc A-Za-z0-9 | head -c 13 ; echo '' Alternatively, to include more characters from the OWASP password special characters list: </dev/urandom tr -dc 'A-Za-z0-9!"#$%&'\''()*+,-./:;<=...


143

The syntax str^^ which you are trying is available from Bash 4.0 and above. Perhaps yours is an older version (or you ran the script with sh explicitly): Try this: str="Some string" printf '%s\n' "$str" | awk '{ print toupper($0) }'


137

To generate a random password you can use pwgen: pwgen generates random, meaningless but pronounceable passwords. These passwords contain either only lowercase letters, or upper and lower case mixed, or digits thrown in. Uppercase letters and digits are placed in a way that eases remembering their position when memorizing only the word. Generate ...


115

Use the tr command echo "/path/to/file /path/to/file2 /path/to/file3 /path/to/file4 /path/to/file5"\ | tr " " "\n" Found on http://www.unix.com/shell-programming-scripting/67831-replace-space-new-line.html


106

I am using the openssl command, the swiss army knife of cryptography. openssl rand -base64 12 or openssl rand -hex 12


105

In a POSIX shell, the syntax ${t:-2} means something different - it expands to the value of t if t is set and non null, and otherwise to the value 2. To trim a single character by parameter expansion, the syntax you probably want is ${t%?} Note that in ksh93, bash or zsh, ${t:(-2)} or ${t: -2} (note the space) are legal as a substring expansion but are ...


89

Use cut with _ as the field delimiter and get desired fields: A="$(cut -d'_' -f2 <<<'one_two_three_four_five')" B="$(cut -d'_' -f4 <<<'one_two_three_four_five')" You can also use echo and pipe instead of Here string: A="$(echo 'one_two_three_four_five' | cut -d'_' -f2)" B="$(echo 'one_two_three_four_five' | cut -d'_' -f4)" Example: $ s=...


79

Have grep read on its standard input. There you go, using a pipe... $ echo "$line" | grep select ... or a here string... $ grep select <<< "$line" Also, you might want to replace spaces by newlines before grepping : $ echo "$line" | tr ' ' '\n' | grep select ... or you could ask grep to print the match only: $ echo "$line" | grep -o select ...


73

echo "lowercase" | tr a-z A-Z Output: LOWERCASE


63

If GNU cat can't write out what it read, it will exit with an error: /* Write this block out. */ { /* The following is ok, since we know that 0 < n_read. */ size_t n = n_read; if (full_write (STDOUT_FILENO, buf, n) != n) die (EXIT_FAILURE, errno, _("write error")); } GNU strings, on the other hand, doesn't care whether it managed to write ...


60

cut sounds like a suitable tool for this: bash-4.2$ s='id;some text here with possible ; inside' bash-4.2$ id="$( cut -d ';' -f 1 <<< "$s" )"; echo "$id" id bash-4.2$ string="$( cut -d ';' -f 2- <<< "$s" )"; echo "$string" some text here with possible ; inside But read is even more suitable: bash-4.2$ IFS=';' read -r id string <<&...


58

for removing the last n characters from a line that makes no use of sed OR awk: > echo lkj | rev | cut -c (n+1)- | rev so for example you can delete the last character one character using this: > echo lkj | rev | cut -c 2- | rev > lk from rev manpage: DESCRIPTION The rev utility copies the specified files to the standard output, ...


48

You can pipe it through awk and make it echo the first word echo * | head -n1 | awk '{print $1;}' or you cut the string up and select the first word: echo * | head -n1 | cut -d " " -f1 or you pipe it thorugh sed and have it remove everything but the first word echo * | head -n1 | sed -e 's/\s.*$//' Added the | head -n1 to satisfy nitpickers. In case ...


48

Using sed it should be as fast as sed 's/.$//' Your single echo is then echo ljk | sed 's/.$//'. Using this, the 1-line string could be any size.


47

You can do case-insensitive substring matching natively in bash using the regex operator =~ if you set the nocasematch shell option. For example s1="hElLo WoRlD" s2="LO" shopt -s nocasematch [[ $s1 =~ $s2 ]] && echo "match" || echo "no match" match s1="gOoDbYe WoRlD" [[ $s1 =~ $s2 ]] && echo "match" || echo "no match" no match


44

bash's printf supports pretty much everything you can do in the printf C function type printf # => printf is a shell builtin printf "%'d" 123456 # => 123,456 printf from coreutils will do the same /usr/bin/printf "%'d" 1234567 # => 1,234,567


39

A few options depending on the shell: POSIX: t=${t%?} Bourne: t=`expr " $t" : ' \(.*\).'` zsh/yash: t=${t[1,-2]} bash/zsh: t=${t:0:-1} ksh93/bash/zsh/mksh: t=${t:0:${#t}-1} ksh93/bash/zsh/mksh: t=${t/%?} ksh93: t=${t/~(E).$/} es: @ {t=$1} ~~ $t *? Note that while all are supposed to strip the last character, you'll find that some implementations (those ...


36

What is sh sh (or the Shell Command Language) is a programming language described by the POSIX standard. It has many implementations (ksh88, dash, ...). bash can also be considered an implementation of sh (see below). Because sh is a specification, not an implementation, /bin/sh is a symlink (or a hard link) to an actual implementation on most POSIX ...


30

The easy way to check that a string only contains characters in an authorized set is to test for the presence of unauthorized characters. Thus, instead of testing whether the string only contains spaces, test whether the string contains some character other than space. In bash, ksh or zsh: if [[ $param = *[!\ ]* ]]; then echo "\$param contains characters ...


28

To extract the part before T, with POSIX shells: time=2017-03-08T19:41:26Z utc_date=${time%T*} # as already said Or to be Bourne compatible or for non-POSIX shells: expr "$time" : '\(.*\)T' Now, note that 2017-03-08T19:41:26Z is the zulu time (another name for UTC), an unambiguous specification of a precise instant in time. At that time, the date was ...


27

You can use a regex in bash (3.0 or above) to accomplish this: if [[ $strname =~ 3(.+)r ]]; then strresult=${BASH_REMATCH[1]} else echo "unable to parse string $strname" fi In bash, capture groups from a regex are placed in the special array BASH_REMATCH. Element 0 contains the entire match, and 1 contains the the match for the first capture group.


26

You can use -b to get the byte offset, which is the same as the position for simple text (but not for UTF-8 or similar). $ echo "RAMSITALSKHMAN|1223333" | grep -aob '|' 14:| In the above, I use the -a switch to tell grep to use the input as text; necessary when operating on binary files, and the -o switch to only output the matching character(s). If you ...


25

As I said in my comment, it's generally not a good idea to parse HTML with Regular Expressions, but you can sometimes get away with it if the HTML you're parsing is well-behaved. In order to only get URLs that are in the href attribute of <a> elements, I find it easiest to do it in multiple stages. From your comments, it looks like you only want the ...


25

Bourne/POSIX-like shells have a split+glob operator and it's invoked every time you leave a parameter expansion ($var, $-...), command substitution ($(...)), or arithmetic expansion ($((...))) unquoted in list context. Actually, you invoked it by mistake when you did for name in ${array[@]} instead of for name in "${array[@]}". (Actually, you should beware ...


25

With GNU sed: sed 's/./\&&/2g' (substitute every (g) character (.) with the same (&) preceded with & (\&) but only starting from the second occurrence (2)). Portably: sed 's/./\&&/g;s/&//' (replace every occurrence, but then remove the first & which we don't want). With some awk implementations (not POSIX as the ...


23

With sed: $ echo "123456789" | sed 's/\([[:digit:]]\{3\}\)\([[:digit:]]\{3\}\)\([[:digit:]]\{3\}\)/\1,\2,\3/g' 123,456,789 (Note that this only works for exactly 9 digits!) or this with sed: $ echo "123456789" | sed ':a;s/\B[0-9]\{3\}\>/,&/;ta' 123,456,789 With printf: $ LC_NUMERIC=en_US printf "%'.f\n" 123456789 123,456,789


Only top voted, non community-wiki answers of a minimum length are eligible