如何从文件中的每一行的字符串中选择第n个字符?

时间:2014-09-02 20:42:02

标签: linux bash sed

每一行都有一个单词和一个数字。我需要以某种方式选择第n个字母,它们将共同构成一个新词。例如:

and 3
for 3
map 2
wrestle 1

draw

它必须像这样开始

cat char.txt | ...

我只允许使用sed(没有awk,perl,......)。

我知道如何选择所有数字

sed 's/\(.*\) \(.*\)/\2/g'

或文字

sed 's/\(.*\) \(.*\)/\1/g'

我正在考虑

cat char.txt | head -c $(sed 's/\(.*\) \(.*\)/\2/g') | tail -c 1 | sed 's/\n\//g'

但是它不会起作用,因为它不会想到所有的线路,并且由于某种原因它甚至不能在一条线路上工作。

需要一些帮助和指导

3 个答案:

答案 0 :(得分:2)

while read w n; do echo -n ${w:(($n-1)):1}; done < filename

输出:

draw

${parameter:offset:length}: 
   Substring Expansion. Expands to up to length characters of parameter
   starting at the character specified by offset.

答案 1 :(得分:2)

这是一个解决这个难题的sed脚本,假设找到的数字在1-9范围内:

s/ /@@@@@@@@@@ /
s/\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\).* 1$/\1/
s/\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\).* 2$/\2/
s/\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\).* 3$/\3/
s/\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\).* 4$/\4/
s/\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\).* 5$/\5/
s/\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\).* 6$/\6/
s/\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\).* 7$/\7/
s/\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\).* 8$/\8/
s/\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\).* 9$/\9/
H
$!D
${x;s/\n//g;}

第一行用@填充当前行上的字,以确保字段中至少有10个字符。 9个后续行用给定位置的字符替换模式空间。 H将该字符存储在保留空间中,前面带有换行符。除非读取了最后一行,否则我们将丢弃模式空间并重新开始。如果已经读取了最后一行,我们将模式空间与保留空间进行交换,保留空间包含用换行符标记的所需单词,我们将其移除。

将其保存在文件script.sed中我们获取

% sed -f script.sed < data
draw

在1-19范围内实施支持角色偏移的版本的迷人练习留给读者练习。

我们可以使用awk更轻松地解决这个难题:

% awk '{answer=answer substr($1,$2,1)}END{print(answer)}' < data
draw

答案 2 :(得分:0)

仅使用sed(抱歉避免使用cat char.txt: - ;

sed -n ':a
/1$/ !{
   s/.//
   h
   s/.* \([0-9]\)$/\1/
   y/98765432/87654321/
   G
   s/\(.\)\n\(.*\) [0-9]/\2 \1/
   b a
   }
s/\(.\).*/\1/p' char.txt

假设您只使用第1列到第9列(单个数字),但可以通过适应“巨大数字”进行扩展。 它也可以通过'简单'在每行写一个字符1 char(所以verticaly)。也可以修改bu重载代码。

<强>释

原则:如果最后一位数字不是1,则删除第一个字符并减少1.如果它等于1,则打印该行的第一个字符。

  • 通过/1$/
  • 测试最后一位数是否为1
  • 减少是通过翻译y/98765432/87654321/
  • 完成的
  • s/.//
  • 删除第一个字符
  • 其他是通过复制线使用工作和保持缓冲区(仅修改最后一位数部分)的演示文稿,只留下数字,减少,添加原始行并重新排列新数字代替最后一个旧数字
  • 到达digit = 1,in不进入流程并仅保留第一个字符,然后按s/\(.\).*/\1/p
  • 打印