#!/usr/bin/env python
#coding: utf-8
#
# self: select field (Open usp Tukubai)
# 
# designed by Nobuaki Tounaka
# written by Ryuichi Ueda
# 
# The MIT License
# 
# Copyright (C) 2011 Universal Shell Programming Laboratory
# 
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# 
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
# 
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

_usage = [ "self f1 f2 ... file", "self -d f1 f2 ... string" ]
_version = "Sat Mar 29 20:29:04 JST 2014"
_code = "Open usp Tukubai (LINUX+FREEBSD/PYTHON2.4+, 3.1, 3.2/UTF-8)"

import re
import sys
import codecs

def die(msg):
	sys.stderr.write( 'Error[self] : ' + msg + "\n")
	sys.exit(1)

def usage():
	sys.stderr.write("Usage     : "+ _usage[0] + "\n")
	sys.stderr.write("          : "+ _usage[1] + "\n")
	sys.stderr.write("Version   : "+ _version + "\n")
	sys.stderr.write("          : "+ _code + "\n")
	sys.exit(1)

def openReadFile(file_name):
	if file_name != "-":
		try:    return codecs.open(file_name,'r','utf-8')
		except: die("ファイルを開けません。")

	if sys.version_info[0] < 3:
		return codecs.getreader('utf-8')(sys.stdin)

	return codecs.getreader('utf-8')(sys.stdin.detach())

def resetStdout():
	if sys.version_info[0] < 3:
		return codecs.getwriter('utf-8')(sys.stdout)

	return codecs.getwriter('utf-8')(sys.stdout.detach())

def isFile(opt):
	# ここではファイルとして扱う文字列を検出
	# .1.2など不正なオプションのチェックはあとで
	
	#絶対パス
	if opt[0] == "/": return True
	#相対パス
	if opt[0] == ".": return True

	for tkn in opt.split("/"):
		p = re.compile('^[0-9\.]+$')
		ret = p.match(tkn)
		if ret != None: return False

		p = re.compile('^NF$')
		ret = p.match(tkn)
		if ret != None: return False
	
		p = re.compile('^NF\.[0-9]*$')
		ret = p.match(tkn)
		if ret != None: return False
	
		p = re.compile('^NF\.[0-9]+\.[0-9]+$')
		ret = p.match(tkn)
		if ret != None: return False
	
		p = re.compile('^NF-[0-9\.]+$')
		ret = p.match(tkn)
		if ret != None: return False

	return True

class Params:
	def __init__(self,tokens):
		self.num_from = None
		self.num_to = None
		self.nf_from = False
		self.nf_to = False
		self.start = None
		self.length = None

		if len(tokens) == 0:
			die("オプションが不正です。")
	
		#フィールド数の処理
		#slashがあれば部分文字列は無い
		if "/" in tokens[0]:
			tmp = tokens[0].split("/")
			self.num_from, self.nf_from = self.parseFieldNum(tmp[0])
			self.num_to, self.nf_to = self.parseFieldNum(tmp[1])
			return

		self.num_from, self.nf_from = self.parseFieldNum(tokens[0])
		self.num_to, self.nf_to = self.num_from, self.nf_from

		if len(tokens) == 1:	return

		#開始位置
		self.start = int(tokens[1])-1
		if len(tokens) == 2:	return

		#文字列の長さ
		self.length = int(tokens[2])

	def parseFieldNum(self,word):
		#1, NF, NF-1 など 
		#数字とNFの有無を返す
		p = re.compile('^[0-9]+$')
		if p.match(word):
			return int(word), False
	
		if word == "NF":
			return 0, True

		tmp = word.split("-")
		if tmp[0] == "NF":
			return int(tmp[1]), True
			
		die("フィールド指定が不正です。")	
		

class Operator:
	def __init__(self):
		self.out_sequence = []
		self.field_num = 0

	def setOption(self,opt):
		params = Params(opt.split('.'))
		self.out_sequence.append(params)

	def output(self,line):
		tokens = [line] + [w for w in line.split(" ") if w != "" ]
		#0: 一行全体 1以降: 各フィールド

		print(" ".join(
			[ self.cutWord(tokens,f) for f in self.out_sequence ]
		))

	def cutWord(self,tokens,param):
		nf = len(tokens)
		frm = param.num_from
		to = param.num_to

		if param.nf_from == True:	frm = nf - frm - 1
		if param.nf_to == True:		to = nf - to - 1

		if param.start == None:
			return " ".join(tokens[frm:to+1])

		token = tokens[frm]
		width = [ self.getCharWidth(ch) for ch in token ]

		#半角だけなら単純に文字列を切り取り
		if not 2 in width:
			if param.start >= len(token):
				die("分割位置が後ろすぎます。")
			if param.length == None:
				return token[param.start:]
			else:
				return token[param.start:param.start+param.length]

		#先頭部分の切り取り
		pos = 0
		wsum = 0
		for w in width:
			if wsum < param.start:
				pos += 1
				wsum += w
			elif wsum > param.start:
				die("不正な分割位置です。")
			else:
				break

		if len(token) <= pos:
			die("分割位置が後ろすぎます。")

		if param.length == None:
			return token[pos:]

		#後ろの切り取り
		leng = 0
		wsum = 0
		for w in width:
			if wsum < param.length:
				leng += 1
				wsum += w

			elif wsum == param.length:
				break
			elif wsum == param.length+1:
				die("不正な分割位置です。")
				
		return token[pos:pos+leng]

	def getCharWidth(self,c):
		x = ord(c)
		if x <= 0x7f:
			return 1 
		if x >= 0xff61 and x <= 0xff9f:
			return 1

		return 2

def directMode(argv):
	for opt in argv[:-1]:
		operator.setOption(opt)

	operator.output(sys.argv[-1])

###########################################
#メイン関数
if __name__ == '__main__':

	if len(sys.argv) <= 1 : usage()
	if '--' in sys.argv : usage()

	operator = Operator()

	#ダイレクトモード
	if sys.argv[1] == "-d":
		directMode(sys.argv[2:])
		sys.exit(0)

	#IOの準備（最後のオプションをファイルかどうか見分ける）
	if isFile(sys.argv[-1]):
		input_file = openReadFile(sys.argv[-1])
		argv = sys.argv[1:-1]
	else:
		input_file = openReadFile("-")
		argv = sys.argv[1:]

	sys.stdout = resetStdout()

	#切り出し位置指定オプションをセット
	for opt in argv:
		operator.setOption(opt)

	#実行
	nf_set = False
	for line in input_file:
		operator.output(line.rstrip())
		nf_set = True

	sys.exit(0)
