Variable quoting difference between bash 4.3.43 and 4.4.19 [closed] - linux

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about a specific programming problem, a software algorithm, or software tools primarily used by programmers. If you believe the question would be on-topic on another Stack Exchange site, you can leave a comment to explain where the question may be able to be answered.
Closed 4 years ago.
Improve this question
Out of curiosity I wonder which change in bash (or head?) made this the following behaviour change,
In 4.4.19 we have the following behaviour,
# Assign "foo <new line> bar" to variabe 'var'
$ > var="foo
bar"
# Echo with and without quotes,
$ > echo "${var}"
foo
bar
$ > echo ${var}
foo bar
# Read all lines (1) except the last,
$ > head -1 <<< ${var}
foo
$ > head -1 <<< "${var}"
foo
Doing the exact same thing in bash 4.2.46 and 4.3.43 results in different output when reading the variable with head.
# Assign "foo <new line> bar" to variabe 'var'
$ > var="foo
bar"
# Echo with and without quotes,
$ > echo "${var}"
foo
bar
$ > echo ${var}
foo bar
$ > head -1 <<< ${var}
foo bar
$ > head -1 <<< "${var}"
foo
So it seems to me (with 4.4.19) that no matter if you quote the variable or not, head's input will be both lines. And with versions 4.2.46 and 4.3.43 the input actually differs depending on if you quote the variable or not.
The earlier behaviour makes sense to me, where you would have to quote the variable if you want the new line. I'm genuinely interested in this behaviour change and the reasoning behind it. I tried looking through the bash-changelog, but nothing obvious stood out to me that would lead to this change (although I have some very vague feeling that I've stumbled on this before).
Thanks in advance!

The behavior in bash 4.3 is a bug which is fixed in 4.4. See the original bug report and
Chet's reply (2015/09).
And the most recent posts to bash mailing list regarding this: the question and Chet's reply (2017/11).

Related

bash printf not working - decimals [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 4 years ago.
Improve this question
Why did printf didn't WORK for the final command printf "%s,%.2f\n" "$s","$a" and what's that extra 0.00 coming from?
When I ran them individually, they worked as expected but not in the final command.
$ s="giga,fifa"; a="8309.18694444444444444444"; echo "$s"; printf "%s\n" "$s"; echo -e "\n"; echo "$a"; printf "%.2f\n" "$a"; echo -e "\n"; echo "$s,$a"; printf "%s" "$s,"; printf "%.2f\n" "$a";echo;printf "%s,%.2f\n" "$s","$a"
giga,fifa
giga,fifa
8309.18694444444444444444
8309.19
giga,fifa,8309.18694444444444444444
giga,fifa,8309.19
giga,fifa,8309.18694444444444444444,0.00
How can I get this output: giga,fifa,8309.19 with just one printf command showing both variables?
You don't use a , in bash printf, you delimit with space. The 0.00 comes from trying to parse the "$s","$a" at once, and has odd results - everything is considered one argument and printed as the first string, so no argument exists for the second and a 0 is substituted as default. This works as expected:
>printf "%s,%.2f\n" "$s" "$a"
giga,fifa,8309.19

grep -1 freezes, but it should report the invalid flag [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about a specific programming problem, a software algorithm, or software tools primarily used by programmers. If you believe the question would be on-topic on another Stack Exchange site, you can leave a comment to explain where the question may be able to be answered.
Closed 6 years ago.
Improve this question
grep -1 gives an error, as it should. But
$ touch foo
$ grep -1 foo
freezes. It doesn't report the invalid flag. Why is this happening? Is it a bug?
I've tested it on Mac (El Capitan) and Ubuntu (14.04).
For modern GNU and MacOS BSD implementations, grep -1 foo is reading from stdin, filtering files for lines containing foo -- which was interpreted as a pattern, not a filename. This differs from grep foo by having the amount of context to print surrounding each match set to a single line, thus being equivalent to grep -C1 foo.
Reading the source to GNU grep, it explicitly allows numbers as short options:
static char const short_options[] =
"0123456789A:B:C:D:EFGHIPTUVX:abcd:e:f:hiLlm:noqRrsuvwxyZz";
These are stored in DEFAULT_CONTEXT, determining how many lines of context to print surrounding each match, unless overridden with the more explicit -A or -B (indicating how many lines to print after of before a match). This is the same value set with -C.
Thus, in the GNU implementation and in BSD implementations extended to behave similarly to it,
grep -C3 foo
...and...
grep -3 foo
...behave identically, printing three lines of context surrounding each match.
To demonstrate this behavior:
$ printf '%s\n' 3 2 1 foo 1 2 3 | grep -0 foo
foo
$ printf '%s\n' 3 2 1 foo 1 2 3 | grep -1 foo
1
foo
1
$ printf '%s\n' 3 2 1 foo 1 2 3 | grep -2 foo
2
1
foo
2
1

How to color ls - l command's columns [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about a specific programming problem, a software algorithm, or software tools primarily used by programmers. If you believe the question would be on-topic on another Stack Exchange site, you can leave a comment to explain where the question may be able to be answered.
Closed 9 years ago.
Improve this question
I wonder if possible to have ls -l colored. I'm not talking about --color, of course.
I found an useful alias for display octal permission in an ls -l command, now, it's possible to color it? In the same way, is possible when I do ls -l, display only permissions in red or something?
I don't know how to use color code, but grep has --color option
If the first line of ls -l is not important to you, you can consider using grep
ls -l | grep --color=always '[d-][r-][w-][x-][r-][w-][x-][r-][w-][x-]'
or in shorter form:
ls -l | grep --color=always '[d-]\([r-][w-][x-]\)\{3\}'
You can use several utilities to do it, like piping the output of ls (OPTIONS...) to supercat (after defiining the rules). Or to highlight (after defining the rules).
Or use awk/sed to pretty print based on regexes. E.g. with gensub in awk, you can insert ANSI color codes to the output...
The first thing that came into my mind is that you can use --color=auto for this:
ls -l --color=auto
And it can be handy to create an alias:
alias lls='ls -l --color=auto'
However I see you don't want that. For that we have to create a more complex function that use the echo -e "colours...":
print_line () {
red='\e[0;31m'
endColor='\e[0m'
first=${1%% *}
rest=${1#* }
echo -e "${red}$first${endColor} $rest"
}
lls () {
IFS=$'\n'; while read line;
do
# echo "$line"
print_line $line
done <<< "$(find $1 -maxdepth 1 -printf '%M %p\n')"
}
If you store them in ~/.bashrc and source it (. ~/.bashrc) then whenever you do lls /some/path it will execute these functions.
If you're asking if there is an option to specify custom column-specific colors in ls, I don't think so. But you can do something like.
> red() { red='\e[0;31m'; echo -ne "${red}$1 "; tput sgr0; echo "${*:2}"; }
> while read -r line; do red $line; done < <(ls -l)

Shell command to extract string within bracket (String) in a variable like status(running) [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I am building a AIX bash shell utility whereby i get a dynamic variable with value like status(running).
I just need the string within brakets that is running.
Right now i am able to get the whole word with status along with the brackets using awk print.
Can anyone suggest me how to just extract the running out of it. Thanks.
Let's say:
s='(running)'
Using pure BASH:
echo "${s//[()]/}"
running
Using sed:
echo "$s" | sed 's/[()]//g'
running
Using tr:
tr -d '()' <<< "$s"
running
UPDATE: As per comments by OP:
s='status(running)'
Using sed:
echo "$s" | sed 's/^.*(\(.*\)).*$/\1/g'
running
Using pure BASH:
t="${s#*\(}"
echo "${t%)*}"
running

How to hide the command when using command repetition with the exclamation mark? [closed]

Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 10 years ago.
Improve this question
When I use ! to execute a previous command it automatically prints the command as well. Is there a way to hide this?
Example:
This is what happens:
ralgrad:~$ echo test
test
ralgrad:~$ !!
echo test
test
This is what I would want:
ralgrad:~$ echo test
test
ralgrad:~$ !!
test
I have looked at the bash source and there is no way to disable this automatic printing of the expanded command. You would have to compile your own version of bash!
If it is particularly important to you for whatever reason, look in bashhist.c in the pre_process_line function and comment out/remove the following line:
printf (stderr, "%s\n", history_value);
You cannot do that with !!, because it repeats the last command not the last output. As far as I know, there is no single command that allows to achieve what you are asking. However, you can try a simple hack:
result=`echo test`
echo "$result"
Well, you can simulate what you want with the following batch file:
if [ -z $1 ]; then
exe=`fc -lrn | awk 'NR==2 {print;}'`
else
exe=`fc -lrn | cut -f2- | awk 'NR>=2 {print;}' | grep "^ $*" | head -n1 `
fi
eval $exe
Let h be the name of the file (or, if you want it, even !). Then you can do:
# echo Foo
Foo
# echo Bar
Bar
# h
Bar
# h echo F
Foo

Resources