The code is ;

case $cm in
declare -a  en
declare -a inf
ec=$(grep -n "! " hw1_out_si_wire.txt)
IFS=$'\n' en=($ec)
lst=$((${#en[@]} -1))
IFS=' ' inf=($en[$lst])
echo " Energy: ${inf[4]} ${inf[5]}"
"in") echo "It's not my problem";;

And I'm trying to take 7th element of $en but the output is ;

[7]ergy: -1090.13343774 Ry

And the $en array is ;

!    total energy              = -1090.13343774 Ry
!    total energy              = -1090.20757070 Ry
!    total energy              = -1090.24296462 Ry
!    total energy              = -1090.25563488 Ry
!    total energy              = -1090.27085564 Ry
!    total energy              = -1090.27693129 Ry
!    total energy              = -1090.28213580 Ry
!    total energy              = -1090.29131927 Ry

So, what is the problem with this code ?Why is the output like this ?

Note:If the informations given is not enough , please inform me.

  • Could the person who voted against say the reason for it ? – onurcanbektas Jun 3 '16 at 9:55
  • 2
    Whenever I see things like [7]tring when I'm expecting somestring [7] I suspect Windows-style CR-LF line-endings are involved – steeldriver Jun 3 '16 at 11:20
  • 1
    Your input file probably has DOS-style line endings. dos2unix it. – Mat Jun 3 '16 at 11:41
  • 3
    I'm voting to close this question as off-topic because it belongs on codereview.stackexchange.com – cas Jun 4 '16 at 4:27
  • 1
    e.g. awk -F'[\r ]+' '/^!/ {c++} ; c==7 { print " Energy:",$5,$6 }' hw1_out_si_wire.txt - this works whether it's a dos text file or unix format. – cas Jun 4 '16 at 10:44

The fact that something is possible to do in bash, doesn't mean that you should, or that it's a good idea. What you are trying to do is much easier in languages like awk or perl.

bash arrays are a fairly advanced usage of bash and, due to limitations in the bash/sh language itself (and the awkwardness of using them), not really as useful as arrays are in other languages. They're great for passing multiple arguments to a command or a function, but of limited use beyond that.

Instead of messing around with bash arrays, try awk.

For example:

#! /bin/sh


case "$cm" in
  out) awk -F'[[:space:]]+' '
           /^!/  {
             if (c==7) {
               print " Energy:",$5,$6;
           };' hw1_out_si_wire.txt ;;

   in) echo "It's not my problem" ;;


 Energy: -1090.28213580 Ry

The embedded awk script counts each line beginning with a !, and when it gets to the 7th line, it prints the 5th and 6th fields.

The -F option sets the field separator to 1-or-more whitespace characters (spaces, tabs, newlines, carriage returns, form-feeds, and vertical tabs). The version in my comment used [\r[:blank:]]+ (which is blank characters, spaces and tabs, plus carriage-return). For your input data, it works the same.

If your version of awk doesn't support regexp field-separators (e.g. mawk) then just drop the -F'[[:space:]]+' from the awk command-line. It will still work, but if the input file is a MS-DOS/Windows text file (i.e. with carriage-return and line-feed as line-ending) rather than a unix text file (with line-feed only as line-ending), it'll output a carriage-return at the end. The carriage-return will be invisible unless piped through cat -v:

 Energy: -1090.28213580 Ry^M

In that case, convert the file to unix format with fromdos first.

| improve this answer | |
  • @leth try the script now, i fixed a bug where it would print all lines it sees while c==7, not just those matching /^!/. Again, remove the -F'[[:space:]]+' option from the awk command line if your awk doesn't support it. – cas Jun 4 '16 at 23:39

Part of the problem is that you're indexing into the en array incorrectly.  When you index into an array, you have to use braces;


| improve this answer | |
  • the last element of $en is the first [0] element of $inf this time. – onurcanbektas Jun 4 '16 at 6:26

Not the answer you're looking for? Browse other questions tagged or ask your own question.