bash: "cut" and "case" help please
This has been driving me mad for 2 days now.
I am trying to automate the detection of a USB soundcard Sometimes it is detected as card 0, sometimes as card 1. I am writing a little script to restart alsa with the appropriate config file. It looks like this, and is run as root Code:
#!/bin/bash This does work (Changes in red): Code:
#!/bin/bash [Yes, I know it's an ugly hack, and I should be using udev-rules, but ...] |
Include the value of cardnum in your output for the *) case, surrounded by quotes. You can always look at it under od if it is unprintable:
mycmd | od -bc Try this program, and you'll spot your error. Pass it an argument, like 0, 1, 2, or nothing at all: Code:
#!/usr/bin/bash |
Thanks for your reply Mr.C (I was wondering if you or tinkster would jump in first ;))
od - how very useful (I am rusty with bash) Code:
tred@p4:~$ grep Bose /proc/asound/cards | cut -c 1 | od -bc Can you explain what is going on? |
See my edit - i hit save too quickly.
|
OK. Thanks for the edit.
Here we go: Code:
tred@p4:~$ ./testcase Code:
tred@p4:~$ cardnum=$(grep Bose /proc/asound/cards | cut -c 1) |
Look very, very, carefully at the difference between your case in... statement and mine.
|
Sorry for the delay - had to go to work.
Thanks for the hint, but.... I have looked very, very carefully at your case in statement and compared it to mine. Yours has quotes around $cardnum mine doesn't. But I did try a variety of quote combinations over the last couple of days (around the variable name, and around the bits before the ")" in the case statement) and got precisely nowhere. If I haven't yet exhausted your patience, please take look at this, which I think illustrates my problem well: Code:
tred@p4:~$ cat testcase The only time this script does as it should is when I unplug the speakers, and it correctly returns "No Bose". I made it print out rawline for you in case you wanted to test this script for yourself. I expect I'll be kicking myself soon, but I just do not understand what is going wrong. Any ideas? I appreciate your input. |
Something's not right here. I perform the same test, using a file with your contents, and your code. It runs as expected:
Code:
$ cat confused.sh Code:
$ cardnum=$(grep Bose cards | cut -c 1) |
I don't know why you are getting the extra character in cut, but you could just use a substring operation in the shell to get that first character.
#!/bin/bash rawline=$(grep Bose $infile) cardnum=${rawline:0:1} ... |
You're right estabroo, at some point you have to throw in the towel. But not too early!
Otherwise, we miss the opportunity to learn important concepts in an environment, such as newline->space translation during shell variable assignment, echo and the actual stream of bytes output (and how -e, -n affects), tools like od to examine the data, shell variable quoting (and how lack of quoting essentially alters the appearance of a language statement), etc. All good learning opportunities here. |
Thanks for your input estabroo.
I have an uneasy feeling that Mr.C knows the answer to my problem and he is quite properly trying to "lead the horse to water" but it (I) won't drink. @Mr.C Quote:
May I ask, what distro are you using? I am running kubuntu 6.06 on the PC I am having problems with. 6.06 is "Long Term Support", and up to date. I'll try running these scripts on some other distros, when I can find time (=now + 1 week). And I'll do an od -bc of my cards file (or more likely the output of grep Bose /proc/asound/cards because I am still not sure where the problem lies. Until later, and thanks :) |
Both NetBSD, and a hand-built 2.4-based linux box. But the important point would be the shell version. It is doing the work.
$ echo $BASH_VERSION 3.2.33(1)-release $ echo $BASH_VERSION 3.2.1(1)-release Add Code:
echo LENGTH: ${#cardnum} Some other considerations - grep is *line* oriented, and lines require proper terminators. The main difference between your environment and mine is that you have the raw data from grep Bose /proc/asound/cards; I had to create a look-alike to test file. Get an od -bc of that /proc/asound/cards file. Your results from: Code:
tred@p4:~$ grep Bose /proc/asound/cards | cut -c 1 | od -bc Code:
tred@p4:~$ echo $cardnum | cut -c 1 | od -bc Code:
$ echo -ne '1\n \n' | od -bc |
I finally cracked it.
I was at work, so only able to play with linux on my laptop. No USB speakers, but I could identify its single soundcard as 0 and the script worked. So when I got home I copied it to my desktop, changed the grep from HDA-Intel to Bose and it didn't work. Here's the moment of enlightenment, on my desktop: Code:
tred@p4:~# cat /proc/asound/cards So my error was not choosing a unique identifier for the line that begins with the soundcard number. The grep "Bose" returned two lines (and I did not realise that the cut would work on both of those lines. Hence the incorrect cardnum not being allocated just "" "0" or "1" So here is the (rc.local) script that finally works properly (until another unforseen situation crops up): Code:
#!/bin/bash -e Now I can go off and add a correction to a previous post ( http://www.linuxquestions.org/questi...efault-649705/ ) about getting USB speakers recognised and auto-configured. |
Always verify your input data, and check your commands in small pieces before chaining long pipelines, esp. with pattern matching.
Change your grep to FORCE looking for a line that starts with a number. Always use as restrictive an RE match as necessary to reduce chances of other unexpected matches: Eg.: grep '^[0-9].*USB-Audio' cards Good job. |
Quote:
You have shown me something(s) useful for the future. Thanks again ;) |
All times are GMT -5. The time now is 05:45 AM. |