Problem whith shell script

Hy guys, I’m trying this while

***#!/bin/bash

echo “Simple test …”
while IFS=";" read -r _name _date _go _back
do
printf '%s %s %s %s
’ “$_name” “$_date” “$_go” “$_back”
done < ./teste.txt
exit 0***

Very simple, my teste.txt file has this content, yes, just two lines

A;2018-02-01;X;X
C;2018-02-01; ;X

I’m getting this

Simple test …
2018-02-01 X X
2018-02-01 X

But, I´d like to get this as result

Simple test …
A 2018-02-01 X X
C 2018-02-01 X

But for this I need to put a space before the first %s, why ?

 printf **'%s** %s %s %s 

’ “$_name” “$_date” “$_go” “$_back”

With the space
printf ’ %s %s %s %s
’ “$_name” “$_date” “$_go” “$_back”

My bash version

GNU bash, versão 4.4.23(1)-release (x86_64-suse-linux-gnu)
Copyright (C) 2016 Free Software Foundation, Inc.
Licença GPLv3+: GNU GPL versão 3 ou posterior <http://gnu.org/licenses/gpl.html>.

Este é um software livre; você é livre para alterar e redistribuí-lo.
Há NENHUMA GARANTIA, na extensão permitida pela lei.

Have a good look at the number of “;” in the line, it’s only three. Put one at the beginning of each line and it will work.

EDIT: And please use CODE tags, the # in the editor. The forums software will parse f.e. two spaces to one. And I bet there are two spaces in the output you show as an example.

Thanks for the answer. I’m working with a csv file. In that I get ; to separate 4 columns. So I need to do this for example ?
;A ;2018/01/02; ; X

The problem is on a friend’s computer, this works, but not mine. But when I put that space it works. My friend uses an older bash version.

I tried to replay what you did by copy/paste of your case above:

henk@boven:~/test/azeva> ls -ltotaal 8
-rwxr--r-- 1 henk wij 161 22 jan 09:27 script
-rw-r--r-- 1 henk wij  34 22 jan 09:28 teste.txt
henk@boven:~/test/azeva> cat script 
#!/bin/bash


echo "Simple test ..."
while IFS=";" read -r _name _date _go _back 
do
printf '%s %s %s %s 
' "$_name" "$_date" "$_go" "$_back"
done < ./teste.txt
henk@boven:~/test/azeva> cat teste.txt 
A;2018-02-01;X;X
C;2018-02-01; ;X
henk@boven:~/test/azeva> ./script 
Simple test ...
A 2018-02-01 X X 
C 2018-02-01   X 
henk@boven:~/test/azeva>

IMHO I get what you expect to get. Thus I can not repeat your problem. ???

@Azeva:
Please check the following:

  1. Has the system file ‘/etc/bash.bashrc’ been changed?
  2. Do you have a ‘/etc/bash.bashrc.local’ file? – If you do then, please post the contents.
  3. Please post the contents of your ‘~/.bashrc’ file.

BTW, you can check how Bash is being initialised by the CLI command “bash -v” – yes, yes, the output is long but, you can check everything which is influencing Bash’s behaviour.

  • And, my test results of your original test script are the same as Henk’s …
  • Therefore, there’s possibly something “unexpected” with respect to the initialisation of your Bash sessions …

Thanks guy,

Here are my answers:

1 - I have installed my SO last week, but yesterday the system has been updated

azevedo@linux-luc7:~/Documentos/PF/Operações/Solaris/planilhas> ls -lah /etc/bash.bashrc
-rw-r--r-- 1 root root 9,5K out 22 09:11 /etc/bash.bashrc

2 - Yes, here it’s.

# /etc/bash.bashrc for SUSE Linux
#
# PLEASE DO NOT CHANGE /etc/bash.bashrc There are chances that your changes
# will be lost during system upgrades.  Instead use /etc/bash.bashrc.local
# for bash or /etc/ksh.kshrc.local for ksh or /etc/zsh.zshrc.local for the
# zsh or /etc/ash.ashrc.local for the plain ash bourne shell  for your local
# settings, favourite global aliases, VISUAL and EDITOR variables, etc ...

#
# Check which shell is reading this file
#
noprofile=false
restricted=false
: ${_is_save:=unset}
if test -z "$is" ; then
 if test -f /proc/mounts ; then
  if ! is=$(readlink /proc/$$/exe 2>/dev/null) ; then
    case "$0" in
    *pcksh)    is=ksh    ;;
    *)        is=sh    ;;
    esac
  fi
  case "$is" in
    */bash)    is=bash
    while read -r -d $'\0' a ; do
        case "$a" in
        --noprofile)
        readonly noprofile=true ;;
        --restricted)
        readonly restricted=true ;;
        esac
    done < /proc/$$/cmdline
    case "$0" in
    sh|-sh|*/sh)
        is=sh    ;;
    esac        ;;
    */ash)    is=ash  ;;
    */dash)    is=ash  ;;
    */ksh)    is=ksh  ;;
    */ksh93)    is=ksh  ;;
    */pdksh)    is=ksh  ;;
    */mksh)    is=ksh  ;;
    */lksh)    is=ksh  ;;
    */*pcksh)    is=ksh  ;;
    */zsh)    is=zsh  ;;
    */*)    is=sh   ;;
  esac
  #
  # `r' in $- occurs *after* system files are parsed
  #
  for a in $SHELL ; do
    case "$a" in
      */r*sh)
        readonly restricted=true ;;
      -r*|-!-]r*|-!-]!-]r*)
        readonly restricted=true ;;
      --restricted)
        readonly restricted=true ;;
    esac
  done
  unset a
 else
  is=sh
 fi
fi

#
# Call common progams from /bin or /usr/bin only
#
path ()
{
    if test -x /usr/bin/$1 ; then
    ${1+"/usr/bin/$@"}
    elif test -x   /bin/$1 ; then
    ${1+"/bin/$@"}
    fi
}


#
# ksh/ash sometimes do not know
#
test -z "$UID"  && readonly  UID=`path id -ur 2> /dev/null`
test -z "$EUID" && readonly EUID=`path id -u  2> /dev/null`

test -s /etc/profile.d/ls.bash && . /etc/profile.d/ls.bash

#
# Avoid trouble with Emacs shell mode
#
if test "$EMACS" = "t" ; then
    path tset -I -Q
    path stty cooked pass8 dec nl -echo
fi

#
# Set prompt and aliases to something useful for an interactive shell
#
case "$-" in
*i*)
    #
    # Set prompt to something useful
    #
    case "$is" in
    bash)
    # If COLUMNS are within the environment the shell should update
    # the winsize after each job otherwise the values are wrong
    case "$(declare -p COLUMNS 2&gt; /dev/null)" in
    *-x*COLUMNS=*) shopt -s checkwinsize
    esac
    # Append history list instead of override
    shopt -s histappend
    # All commands of root will have a time stamp
    if test "$UID" -eq 0  ; then
        HISTTIMEFORMAT=${HISTTIMEFORMAT:-"%F %H:%M:%S "}
    fi
    # Force a reset of the readline library
    unset TERMCAP
    #
    # Returns short path (last two directories)
    #
    spwd () {
      ( IFS=/
        set $PWD
        if test $# -le 3 ; then
        echo "$PWD"
        else
        eval echo \"..\${$(($#-1))}/\${$#}\"
        fi ) ; }
    #
    # Set xterm prompt with short path (last 18 characters)
    #
    if path tput hs 2&gt;/dev/null || path tput -T $TERM+sl hs 2&gt;/dev/null ; then
        #
        # Mirror prompt in terminal "status line", which for graphical
        # terminals usually is the window title. KDE konsole in
        # addition needs to have "%w" in the "tabs" setting, ymmv for
        # other console emulators.
        #
        if  $TERM = *xterm* ]] ; then
        _tsl=$(echo -en '\e]2;')
        _isl=$(echo -en '\e]1;')
        _fsl=$(echo -en '\007')
        elif path tput -T $TERM+sl tsl 2&gt;/dev/null ; then
        _tsl=$(path tput -T $TERM+sl tsl 2&gt;/dev/null)
        _isl=''
        _fsl=$(path tput -T $TERM+sl fsl 2&gt;/dev/null)
        else
        _tsl=$(path tput tsl 2&gt;/dev/null)
        _isl=''
        _fsl=$(path tput fsl 2&gt;/dev/null)
        fi
        _sc=$(tput sc 2&gt;/dev/null)
        _rc=$(tput rc 2&gt;/dev/null)
        if test -n "$_tsl" -a -n "$_isl" -a "$_fsl" ; then
        TS1="$_sc$_tsl%s@%s:%s$_fsl$_isl%s$_fsl$_rc"
        elif test -n "$_tsl" -a "$_fsl" ; then
        TS1="$_sc$_tsl%s@%s:%s$_fsl$_rc"
        fi
        unset _isl _tsl _fsl _sc _rc
        ppwd () {
        local dir
        local -i width
        test -n "$TS1" || return;
        dir="$(dirs +0)"
        let width=${#dir}-18
        test ${#dir} -le 18 || dir="...${dir#$(printf "%.*s" $width "$dir")}"
        if test ${#TS1} -gt 17 ; then
            printf "$TS1" "$USER" "$HOST" "$dir" "$HOST"
        else
            printf "$TS1" "$USER" "$HOST" "$dir"
        fi
        }
    else
        ppwd () { true; }
    fi
    # If set: do not follow sym links
    # set -P
    #
    # Other prompting for root
    if test "$UID" -eq 0  ; then
        if test -n "$TERM" -a -t ; then
            _bred="$(path tput bold 2&gt; /dev/null; path tput setaf 1 2&gt; /dev/null)"
            _sgr0="$(path tput sgr0 2&gt; /dev/null)"
        fi
        # Colored root prompt (see bugzilla #144620)
        if test -n "$_bred" -a -n "$_sgr0" ; then
        _u="\$_bred\]\h"
        _p=" #\$_sgr0\]"
        else
        _u="\h"
        _p=" #"
        fi
        unset _bred _sgr0
    else
        _u="\u@\h"
        _p="&gt;"
    fi
    if test -z "$EMACS" -a -z "$MC_SID" -a "$restricted" != true -a \
        -z "$STY" -a -n "$DISPLAY" -a ! -r $HOME/.bash.expert
    then
        _t="\\$(ppwd)\]"
    else
        _t=""
    fi
    case "$(declare -p PS1 2&gt; /dev/null)" in
    *-x*PS1=*)
        ;;
    *)
        # With full path on prompt
        PS1="${_t}${_u}:\w${_p} "
#        # With short path on prompt
#        PS1="${_t}${_u}:\$(spwd)${_p} "
#        # With physical path even if reached over sym link
#        PS1="${_t}${_u}:\$(pwd -P)${_p} "
        ;;
    esac
    unset _u _p _t
    ;;
    ash)
    cd () {
        local ret
        command cd "$@"
        ret=$?
        PWD=$(pwd)
        if test "$UID" = 0 ; then
        PS1="${HOST}:${PWD} # "
        else
        PS1="${USER}@${HOST}:${PWD}&gt; "
        fi
        return $ret
    }
    cd .
    ;;
    ksh)
    # Some users of the ksh are not common with the usage of PS1.
    # This variable should not be exported, because normally only
    # interactive shells set this variable by default to ``$ ''.
    if test "${PS1-\$ }" = '$ ' -o "${PS1-\$ }" = '# ' ; then
        if test "$UID" = 0 ; then
        PS1="${HOST}:"'${PWD}'" # "
        else
        PS1="${USER}@${HOST}:"'${PWD}'"> "
        fi
    fi
    ;;
    zsh)
#    setopt chaselinks
    if test "$UID" = 0; then
        PS1='%n@%m:%~ # '
    else
        PS1='%n@%m:%~> '
    fi
    ;;
    *)
    if test "$UID" = 0 ; then
        PS1="${HOST}:"'${PWD}'" # "
    else
        PS1="${USER}@${HOST}:"'${PWD}'"> "
    fi
    ;;
    esac
    PS2='> '

    if test "$is" = "ash" ; then
    # The ash shell does not have an alias builtin in
    # therefore we use functions here. This is a seperate
    # file because other shells may run into trouble
    # if they parse this even if they do not expand.
    test -s /etc/profile.d/alias.ash && . /etc/profile.d/alias.ash
    else
    test -s /etc/profile.d/alias.bash && . /etc/profile.d/alias.bash
    test -s $HOME/.alias && . $HOME/.alias
    fi

    #
    # Expert mode: if we find $HOME/.bash.expert we skip our settings
    # used for interactive completion and read in the expert file.
    #
    if test "$is" = "bash" -a -r $HOME/.bash.expert ; then
    . $HOME/.bash.expert
    elif test "$is" = "bash" ; then
    # Complete builtin of the bash 2.0 and higher
    case "$BASH_VERSION" in
    [2-9].*)
        if test -e /etc/bash_completion ; then
        . /etc/bash_completion
        elif test -s /etc/profile.d/bash_completion.sh ; then
        . /etc/profile.d/bash_completion.sh
        elif test -s /etc/profile.d/complete.bash ; then
        . /etc/profile.d/complete.bash
        fi
        # Do not source twice if already handled by bash-completion
        if  -n $BASH_COMPLETION_COMPAT_DIR && $BASH_COMPLETION_COMPAT_DIR != /etc/bash_completion.d ]]; then
        for s in /etc/bash_completion.d/*.sh ; do
            test -r $s && . $s
        done
        fi
        if test -e $HOME/.bash_completion ; then
        . $HOME/.bash_completion
        fi
        if test -f /etc/bash_command_not_found ; then
        . /etc/bash_command_not_found
        fi
        ;;
    *)  ;;
    esac
    fi

    # Do not save dupes and lines starting by space in the bash history file
    HISTCONTROL=ignoreboth
    if test "$is" = "ksh" ; then
    # Use a ksh specific history file and enable
        # emacs line editor
        : ${HISTFILE=$HOME/.kshrc_history}
        : ${VISUAL=emacs}
    case $(set -o) in
    *multiline*) set -o multiline
    esac
    fi
    # command not found handler in zsh version
    if test "$is" = "zsh" ; then
    if test -f /etc/zsh_command_not_found ; then
        . /etc/zsh_command_not_found
    fi
    fi
    ;;
esac

# Source /etc/profile.d/vte.sh, which improvies usage of VTE based terminals.
# It is vte.sh's responsibility to 'not load' when it's not applicable (not inside a VTE term)
# If you want to 'disable' this functionality, set the sticky bit on /etc/profile.d/vte.sh
if test -r /etc/profile.d/vte.sh -a ! -k /etc/profile.d/vte.sh; then
  . /etc/profile.d/vte.sh
fi

#
# Set GPG_TTY for curses pinentry
# (see man gpg-agent and bnc#619295)
#
if test -t && type -p tty > /dev/null 2>&1 ; then
    GPG_TTY="`tty`"
    export GPG_TTY
fi

#
# And now let us see if there is e.g. a local bash.bashrc
# (for options defined by your sysadmin, not SUSE Linux)
#
case "$is" in
bash) test -s /etc/bash.bashrc.local && . /etc/bash.bashrc.local ;;
ksh)  test -s /etc/ksh.kshrc.local   && . /etc/ksh.kshrc.local ;;
zsh)  test -s /etc/zsh.zshrc.local   && . /etc/zsh.zshrc.local ;;
ash)  test -s /etc/ash.ashrc.local   && . /etc/ash.ashrc.local
esac
test -s /etc/sh.shrc.local && . /etc/sh.shrc.local

if test "$_is_save" = "unset" ; then
    #
    # Just in case the user excutes a command with ssh or sudo
    #
    if test \( -n "$SSH_CONNECTION" -o -n "$SUDO_COMMAND" \) -a -z "$PROFILEREAD" -a "$noprofile" != true ; then
    _SOURCED_FOR_SSH=true
    . /etc/profile > /dev/null 2>&1
    unset _SOURCED_FOR_SSH
    fi
    unset is _is_save
fi

if test "$restricted" = true -a -z "$PROFILEREAD" ; then
    PATH=/usr/lib/restricted/bin
    export PATH
fi
#
# End of /etc/bash.bashrc
#


3 - I have changed nothing yet.

# Sample .bashrc for SuSE Linux
# Copyright (c) SuSE GmbH Nuernberg

# There are 3 different types of shells in bash: the login shell, normal shell
# and interactive shell. Login shells read ~/.profile and interactive shells
# read ~/.bashrc; in our setup, /etc/profile sources ~/.bashrc - thus all
# settings made here will also take effect in a login shell.
#
# NOTE: It is recommended to make language settings in ~/.profile rather than
# here, since multilingual X sessions would not work properly if LANG is over-
# ridden in every subshell.

# Some applications read the EDITOR variable to determine your favourite text
# editor. So uncomment the line below and enter the editor of your choice :-)
#export EDITOR=/usr/bin/vim
#export EDITOR=/usr/bin/mcedit

# For some news readers it makes sense to specify the NEWSSERVER variable here
#export NEWSSERVER=your.news.server

# If you want to use a Palm device with Linux, uncomment the two lines below.
# For some (older) Palm Pilots, you might need to set a lower baud rate
# e.g. 57600 or 38400; lowest is 9600 (very slow!)
#
#export PILOTPORT=/dev/pilot
#export PILOTRATE=115200

test -s ~/.alias && . ~/.alias || true


Roger that. I’ll use CODE. Thanks.

Brothers, I found the problem, I don’t know the explanation for this, but it works …

My original code:

#!/bin/bash

echo "Simple test ..."
while IFS=";" read -r _name _date _go _back 
do
     printf '%s %s %s %s 
' "$_name" "$_date" "$_go" "$_back"
#     echo $_name $_date $_go $_back
#done < <(echo "a;2018-01-17;X;X;" && echo "b;2018-01-18; ;X;" && echo "C;2018-01-18;X;X;")
done < ./teste.txt
exit 0

My test file:

azevedo@linux-luc7:~/Documentos/PF/Operações/Solaris/planilhas> cat teste.txt 
A;2018-02-01;X;X
C;2018-02-01; ;X
azevedo@linux-luc7:~/Documentos/PF/Operações/Solaris/planilhas>

My output for the original code:

azevedo@linux-luc7:~/Documentos/PF/Operações/Solaris/planilhas> ./completarPeriodosTeste.sh 
Simple test ...
  2018-02-01 X X
  2018-02-01   X
azevedo@linux-luc7:~/Documentos/PF/Operações/Solaris/planilhas> 

My change:

#!/bin/bash

echo "Simple test ..."
while IFS=";" read -r _name _date _go _back 
do
     printf '%s %s %s %s
' "$_name" "$_date" "$_go" "$_back"
#     echo $_name $_date $_go $_back
#done < <(echo "a;2018-01-17;X;X;" && echo "b;2018-01-18; ;X;" && echo "C;2018-01-18;X;X;")
done < ./teste.txt
exit 0

My new output:

azevedo@linux-luc7:~/Documentos/PF/Operações/Solaris/planilhas> ./completarPeriodosTeste.sh 
Simple test ...
A 2018-02-01 X X
C 2018-02-01   X
azevedo@linux-luc7:~/Documentos/PF/Operações/Solaris/planilhas> 

The modification from this:

 printf '%s %s %s %s 
' "$_name" "$_date" "$_go" "$_back"

To this:

 printf '%s %s %s %s
' "$_name" "$_date" "$_go" "$_back"

Any jedi master can , please, explain his when having some time ?

:::\

The time stamp of your ‘/etc/bash.bashrc’ file corresponds to the (updated) time stamp on this Leap 15.0 system …

I compared your ‘/etc/bash.bashrc’ with the copy on this system – they’re identical …

  • In other words, your ‘/etc/bash.bashrc’ hasn’t been edited and, you don’t have any changes deployed by a system administrator – no customisations executed via ‘/etc/bash.bashrc.local
    ’ …

And, your user’s “.bashrc” also doesn’t contain any changes to the factory settings …
[HR][/HR]Suggestion: but, please, don’t post the output here – please use either <SUSE Paste; or <SUSE Paste

  • Dump the output of “set” to a file – on this system it’s 3608 lines long – and check if there’s anything which is not as it should be.
  • Compare your “set” output to that of “set” on the system where the Bash script behaves as expected.

You mean you removed the space character before the newline indication?

I can not explain that. The more because, as I have shown, I do not have the problem at all. And I am not alone in not being able to reconstruct your problem.

Yes, I did only that, nothing more.

bor@bor-Latitude-E5450:/tmp$ ./foo1.sh
Simple test ...
  2018-02-01 X X
  2018-02-01   X
bor@bor-Latitude-E5450:/tmp$ ./foo2.sh
Simple test ...
A 2018-02-01 X X
C 2018-02-01   X
bor@bor-Latitude-E5450:/tmp$ cat teste.txt 
A;2018-02-01;X;X
C;2018-02-01; ;X
bor@bor-Latitude-E5450:/tmp$ hexdump -C teste.txt 
00000000  41 3b 32 30 31 38 2d 30  32 2d 30 31 3b 58 3b 58  |A;2018-02-01;X;X|
00000010  0d 0a 43 3b 32 30 31 38  2d 30 32 2d 30 31 3b 20  |..C;2018-02-01; |
00000020  3b 58 0d 0a                                       |;X..|
00000024
bor@bor-Latitude-E5450:/tmp$ 

Oh, a DOS-/Windows line ending (hex 0d == carriage return, 0a == new line, aka line feed) — it’s not a UNIX text file. Yup, that can screw up your parsing. :wink:

Either read over the 0x0d bytes while parsing, or filter them out, or use the dos2unix command to convert the file(s) with DOS linebreaks into files with Unix linebreaks beforehand.

It’s funny that, in our 21th century full of Unicode text with even hundreds of emoji defined, those 40-years old line-break bugs can still bite us.
Cheers!

@Azeva:

Take a look at the output of “file” with respect to the CSV input file:


 > file testeDOS.txt teste.txt
testeDOS.txt: ASCII text, with CRLF line terminators
teste.txt:    ASCII text
 > 

Thanks brothers !!!

:good::good::good:
Thanks man !!!