28

Here is my sample.txt file it contains following

31113    70:54:D2 - a-31003
31114    70:54:D2 - b-31304
31111    4C:72:B9 - c-31303
31112    4C:72:B9 - d-31302

I have to write the shell script in that I am passing first 5 characters (eg 31113) as input id to other script. For this I have tried this

#!/bin/sh
filename='sample.txt'
filelines=`cat $filename`
while read -r line
do
  id= cut -c-5 $line
  echo $id
  #code for passing id to other script file as parameter
done < "$filename"

but it is not working this gives me error as

cut: 31113: No such file or directory
cut: 70:54:D2 No such file or directory
31114
31111
31112
: No such file or directory

How can I do this?

fedorqui
  • 275,237
  • 103
  • 548
  • 598
user2622247
  • 1,059
  • 2
  • 15
  • 26

8 Answers8

36

If you want to use cut this way, you need to use redirection <<< (a here string) like:

var=$(cut -c-5 <<< "$line")

Note the use of var=$(command) expression instead of id= cut -c-5 $line. This is the way to save the command into a variable.

Also, use /bin/bash instead of /bin/sh to have it working.


Full code that is working to me:

#!/bin/bash

filename='sample.txt'
while read -r line
do
  id=$(cut -c-5 <<< "$line")
  echo $id
  #code for passing id to other script file as parameter
done < "$filename"
fedorqui
  • 275,237
  • 103
  • 548
  • 598
  • 1
    It does work, but this is not the idiomatic way to write this! – William Pursell Jan 07 '14 at 12:31
  • 1
    Small semantics note, that's typically referred to as "redirection" not "indirection." ("indirection" is usually used to mean "nonlinear paths through the code") – floer32 Feb 26 '16 at 00:19
  • 1
    more understandable:`cut -c -5` only prints the first 5 characters. This is even better to read: `cut -c 1-5` – rubo77 Apr 16 '20 at 23:15
28

Well, its a one-liner cut -c-5 sample.txt. Example:

$ cut -c-5 sample.txt 
31113
31114
31111
31112

From there-on, you can pipe it to any other script or command:

$ cut -c-5 sample.txt | while read line; do echo Hello $line; done
Hello 31113
Hello 31114
Hello 31111
Hello 31112
tuxdna
  • 8,257
  • 4
  • 43
  • 61
8

Rather than piping echo into cut, just pipe the output of cut directly to the while loop:

cut -c 1-5 sample.txt |
while read -r id; do
  echo $id
  #code for passing id to other script file as parameter
done
William Pursell
  • 204,365
  • 48
  • 270
  • 300
  • Why do you need the while loop? – RedX Jan 07 '14 at 12:13
  • 2
    The while loop is totally unnecessary if the only command is `echo`, but I presume there is more happening in the real script, which is held by the placeholder: `#code for passing id to other script file as parameter` – William Pursell Jan 07 '14 at 12:15
3

Maybe you need this, awk can recognize white space automatically.

awk '{print $1}' sample.txt
BMW
  • 42,880
  • 12
  • 99
  • 116
  • 1
    And how exactly does this print the first 5 chars of every line of sample.txt? – RedX Jan 07 '14 at 12:06
  • You see, vanda answer the question with similar way, this makes sense for you now? sometimes, the requesters didn't know how to express their request properly. – BMW Jan 07 '14 at 12:09
  • hehe, you really focus on it, Rep is nothing. – BMW Jan 07 '14 at 12:13
  • +1: In the case specified in the question, the first 5 characters are also the first field of space delimited text, so this answer is a perfectly reasonable approach. – William Pursell Jan 07 '14 at 12:13
  • @WilliamPursell Yeah, vanda explained it. Thanks for your explanation too. – RedX Jan 07 '14 at 12:18
3

Please check the following simple example:

while read line; do id=$(echo $line | head -c5); echo $id; done < file

where head -c5 is the right command to get the first 5 characters from the string.

kenorb
  • 155,785
  • 88
  • 678
  • 743
1

If you trying to fetch the first column from file try awk:

#!/bin/sh
filename='sample.txt'

while read -r line
do
  id=$(echo $line | awk '{print $1}')
  echo $id
  #code for passing id to other script file as parameter
done < "$filename"
vahid abdi
  • 9,636
  • 4
  • 29
  • 35
  • And how exactly does this print the first 5 chars of every line of sample.txt? – RedX Jan 07 '14 at 12:11
  • @RedX `awk` separator each line by (`space` by default) and print the first field (`'{print $1}'`) which is the first 5 chars. – vahid abdi Jan 07 '14 at 12:16
0

Somewhat simpler than the top answer:

#!/bin/bash
filename='sample.txt'
while read -r line; do
  id=${line:0:5}
  echo $id
  #code for passing id to other script file as parameter
done < "$filename"
Wybo Dekker
  • 132
  • 6
0

Use sed with a capture group that matches the first 5 characters and returns only that group:

sed -E 's/(.{0,5}).*/\1/' sample.txt

(.{0,5}) greedily matches any character up to 5 times, and creates a capture group.

.* matches the rest of the line, because we want to replace the entire line, not just the capture group.

\1 is a backreference which refers to the first capture group.

So we are capturing the group of 5 characters we want, and then replacing the entire matched line with only that capture group.

philraj
  • 820
  • 6
  • 13