 |
 |
 |
 |
| Programming & Packaging A place to discuss programming and packaging. |

1st April 2012, 12:08 PM
|
 |
Registered User
|
|
Join Date: Oct 2009
Location: /home
Posts: 65

|
|
|
Little Bash Problem
Hi, I'm out to write a script which reads a text file and copies all words into another text file if their length is 8.
But I can't get it work :[
Code:
#!/bin/sh
for word in $(cat list1.txt); do
if [ $(#word) -eq 8 ]; then
echo $word >> list2.txt
fi
done
Can somebody tell me what is wrong?
__________________
There are only 10 types of people in the world: Those who understand binary and those who don't.
|

1st April 2012, 12:48 PM
|
 |
Un-Retired Administrator
|
|
Join Date: Mar 2004
Location: Salem, Mass USA
Posts: 13,924

|
|
|
Re: Little Bash Problem
Replace the () with {}
PHP Code:
if [ ${#word} -eq 8 ] ; then
This seems to work for me.
__________________
Glenn
The Bassinator © ®
Laptop: Toshiba Satellite / Intel Core 2 Duo 1.73 GHz / 2GB / 160GB / Intel Mobile 945GM/GMS/GME/943/940GML Integrated Graphics
Desktop: BioStar MCP6PB M2+ / AMD Phenom 9750 Quad Core / 4GB / 1TB SATA / 500GB SATA / EVGA GeForce 8400 GS 1GB
|

1st April 2012, 01:14 PM
|
 |
Registered User
|
|
Join Date: Oct 2009
Location: /home
Posts: 65

|
|
|
Re: Little Bash Problem
Yes it works. Thanks!
But can you explain me why? The syntax confuses me.
__________________
There are only 10 types of people in the world: Those who understand binary and those who don't.
|

1st April 2012, 01:22 PM
|
|
Registered User
|
|
Join Date: Aug 2009
Location: Waldorf, Maryland
Posts: 6,089

|
|
|
Re: Little Bash Problem
() is used to designate a subprocess to be executed
{} is used to encapsulate a variable that may be confused with characters outside the {}.
$ is used to signify a substition point - hence $( makes no sense.
Now arithemtic expressions are identified by $((<expression>))
might have worked.
|

1st April 2012, 08:32 PM
|
|
Official Gnome 3 Sales Rep. (and Adminstrator)
|
|
Join Date: Jul 2011
Location: Leamington Spa, UK
Age: 30
Posts: 1,689

|
|
|
Re: Little Bash Problem
Quote:
Originally Posted by jpollard
$ is used to signify a substition point - hence $( makes no sense.
|
Just to clarify, $(command) does make sense, and captures the output of a command. It's a more modern syntax for `command` (with back-ticks rather than single-quotes, which mean a literal string with no internal substitutions in shell-script). However, variables are expanded with $var or ${var}.
So:
Code:
# Literal string with internal substitution (spaces do not split tokens):
$ echo "$PATH"
/usr/lib64/ccache:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/gareth/.local/bin:/home/gareth/bin
# Literal string without internal substitution (spaces do not split tokens):
$ echo '$PATH'
$PATH
# Capture command output:
$ echo `ls /`
bin boot dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
$ echo $(ls /)
bin boot dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
# Substitute a variable (spaces split tokens unless the variable is double-quoted):
$ echo $PATH
/usr/lib64/ccache:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/gareth/.local/bin:/home/gareth/bin
$ echo ${PATH}
/usr/lib64/ccache:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/gareth/.local/bin:/home/gareth/bin
# Do integer maths:
$ echo $((1 + 23))
24
$ echo $[1 + 23]
24
---------- Post added at 08:32 PM ---------- Previous post was at 08:27 PM ----------
I'd also make the following (very minor!) optimizations:
Code:
#!/bin/sh
for word in $(< list1.txt); do
if [ ${#word} -eq 8 ]; then
echo $word >> list2.txt
fi
done > list2.txt
The first change uses the bash internal file reader rather than running cat as a separate process.
The second causes list2.txt to only be opened and closed once.
|

2nd April 2012, 01:03 AM
|
 |
Registered User
|
|
Join Date: Apr 2006
Location: Ohio, USA
Posts: 8,298

|
|
|
Re: Little Bash Problem
Quote:
Originally Posted by jpollard
() is used to designate a subprocess to be executed
|
No - wrong - it's a SUB-SHELL - same shell but new environment - NOT a subprocess.
Also () can be used to modify default precedence, pattern matching in a case statement, in bash function declarations, in array assignment ; e.g: FOO=([0]="foo" [1]="bar" [2]="baz")
Used as <(list) or >(list) to create pipes.
Quote:
|
{} is used to encapsulate a variable that may be confused with characters outside the {}.
|
More accurately ....
Quote:
${parameter}
The value of parameter is substituted. The braces are required when parameter is a positional parameter with more than one digit, or when parameter is followed by a character which is not to be interpreted as part of its name.
|
So it delimits parameters where there is the possibility of confusion. A shell variable is one type of parameter, and that's only one of several uses for braces. Brace expansion, function declaration, same-shell lists, ...
Quote:
Originally Posted by Gareth Jones
Just to clarify, ....
|
Excellent changes.
__________________
None are more hopelessly enslaved than those who falsely believe they are free.
Johann Wolfgang von Goethe
|

2nd April 2012, 01:55 AM
|
|
Official Gnome 3 Sales Rep. (and Adminstrator)
|
|
Join Date: Jul 2011
Location: Leamington Spa, UK
Age: 30
Posts: 1,689

|
|
|
Re: Little Bash Problem
Quote:
Originally Posted by stevea
No - wrong - it's a SUB-SHELL - same shell but new environment - NOT a subprocess.
|
A "( command )" sub-shell is generally implemented as a separate child process of the main shell though. "{ command ;}" is similar, but tries to run commands in the current shell whenever possible (pipes for example make that difficult):
Code:
[gareth@gareth-desktop ~]$ echo $BASHPID # Main shell process ID.
19613
[gareth@gareth-desktop ~]$ ( echo $BASHPID ) # Subshell has new PID.
19717
[gareth@gareth-desktop ~]$ { echo $BASHPID; } # Should have same PID.
19613
[gareth@gareth-desktop ~]$ echo hello | { echo $BASHPID; cat ;} # Pipe forces sub-shell.
19761
hello
Note that $$ always expands to the main shell's PID, so you have to use $BASHPID to catch the sub-shell.
|

2nd April 2012, 06:11 AM
|
 |
Registered User
|
|
Join Date: Nov 2006
Location: Detroit
Posts: 4,612

|
|
|
Re: Little Bash Problem
I prefer to use a while loop:
Code:
#!/bin/bash
while read -r word; do
if [ ${#word} -eq 8 ]; then
echo $word
fi
done < list1.txt > list2.txt
__________________
OS: Fedora 18 x86_64 | CPU: AMD64 3700+ 2.2GHz | RAM: 2GB PC3200 DDR | Disk: 160GB PATA | Video: ATI Radeon 7500 AGP 64MB | Sound: Turtle Beach Santa Cruz CS4630 | Ethernet: Realtek 8110SC
|

2nd April 2012, 07:36 AM
|
 |
Registered User
|
|
Join Date: Apr 2006
Location: Ohio, USA
Posts: 8,298

|
|
|
Re: Little Bash Problem
Quote:
Originally Posted by Gareth Jones
A "( command )" sub-shell is generally implemented as a separate child process of the main shell though. "{ command ;}" is similar, but tries to run commands in the current shell whenever possible (pipes for example make that difficult):
|
Thanks - I haven't examinined the implementation in many years - but it it's create using ...
strace -f -etrace=clone,execve bash
So both "(cmd)" and "cmd&" so a fork a subprocess currently, and neither does an exec (aside from any exceutable cmd exec). "{cmd;}", as expected executes w/o any extra process creation.
I don't think your comments about pipes is clear (and maybe not accurate). We expect pipes "|" to create new processes .... for example
ls | wc -l
vs
{ ls | wc -l; }
have the same process creation events. Ignoring the execve() calls for the executables, there is always one clone() "aka fork" call per pipe .....
(output line length below trimmed for clarity)
Quote:
[stevea@crucibulum Desktop]$ ls | wc -l
clone(Process 24114 attached
[pid 23534] clone(Process 24115 attached
Process 23534 suspended
[pid 24114] execve("/bin/ls", ["ls"], [/* 49 vars */]) = 0
[pid 24115] execve("/usr/bin/wc", ["wc", "-l"], [/* 49 vars */]) = 0
17
Process 23534 resumed
Process 24114 detached
Process 24115 detached
[stevea@crucibulum Desktop]$ { ls | wc -l; }
clone(Process 24116 attached
[pid 23534] clone(Process 24117 attached
Process 23534 suspended
[pid 24116] execve("/bin/ls", ["ls"], [/* 49 vars */]) = 0
[pid 24117] execve("/usr/bin/wc", ["wc", "-l"], [/* 49 vars */]) = 0
Process 23534 resumed
Process 24116 detached
17
Process 23534 suspended
Process 23534 resumed
Process 24117 detached
|
__________________
None are more hopelessly enslaved than those who falsely believe they are free.
Johann Wolfgang von Goethe
|

2nd April 2012, 02:13 PM
|
 |
Registered User
|
|
Join Date: Oct 2009
Location: /home
Posts: 65

|
|
|
Re: Little Bash Problem
Ok, thanks for all the answers
__________________
There are only 10 types of people in the world: Those who understand binary and those who don't.
|

2nd April 2012, 02:55 PM
|
|
Official Gnome 3 Sales Rep. (and Adminstrator)
|
|
Join Date: Jul 2011
Location: Leamington Spa, UK
Age: 30
Posts: 1,689

|
|
|
Re: Little Bash Problem
Quote:
Originally Posted by RupertPupkin
I prefer to use a while loop:
Code:
#!/bin/bash
while read -r word; do
if [ ${#word} -eq 8 ]; then
echo $word
fi
done < list1.txt > list2.txt
|
That's the best way I think.
---------- Post added at 02:55 PM ---------- Previous post was at 02:51 PM ----------
Quote:
Originally Posted by stevea
I don't think your comments about pipes is clear (and maybe not accurate). We expect pipes "|" to create new processes
|
Yes, I was probably going into too much detail and then over-simplifying it back. The reason I thought of it is that I remember some other Bourne shell derivatives (ksh maybe?) can run the last part of a pipe-line in the top-level shell so that you can read into shell variables etc. for use later. In Bash you'd have to use process substitution instead I think. But none of that directly relates to sub-shell syntaxes of course.
|
| Thread Tools |
Search this Thread |
|
|
|
| Display Modes |
Linear Mode
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
Similar Threads
|
| Thread |
Thread Starter |
Forum |
Replies |
Last Post |
|
bash problem
|
HayZam |
Using Fedora |
4 |
25th January 2008 01:39 PM |
|
bash problem
|
mohdfarah |
Programming & Packaging |
0 |
17th September 2006 12:41 PM |
Current GMT-time: 11:33 (Saturday, 18-05-2013)
|
|
 |
 |
 |
 |
|
|